3 Replies Latest reply on Mar 19, 2009 3:29 AM by Ingo Jobling

    understanding transactions and flushMode=MANUAL

    Arbi Sookazian Master

      I have the following Seam SFSB component which is acting as a backing bean for a JSF.  It loops thru the List of serialNumber variables entered in the JSF form and persists records to the db table.


      Pertinent code:


      @Begin(join=true, flushMode=FlushModeType.MANUAL)
          @TransactionAttribute(TransactionAttributeType.REQUIRED)
          public void searchSerialNumbers()
           {                    
                //parse serial numbers from HtmlInputTextarea control....
                List<String> serialNumberList = parseSerialNumber();
                
                if (serialNumberList != null && serialNumberList.size() > 0)
                {
                     for (String serialNumber : serialNumberList)  //persist records one serialNumber at a time...
                     {
                          this.persistA();
      
                                      //cause ArrayIndexOutOfBoundsException to be thrown
                          String[] sArray = new String[4];
                          String s = sArray[10];
      
                          this.persistB();
                          
                     }
                }          
           }
          
          @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
          private void persistA()
          {
               TestTransactions testTransactions = new TestTransactions();
                testTransactions.setSerialNumber(serialNumber);
                testTransactions.setAddedDate(new Date());
                entityManager.persist(testTransactions);
                entityManager.flush();
          }
          
          @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
          private void persistB()
          {
               TestTransactions testTransactions = new TestTransactions();
                testTransactions.setSerialNumber(serialNumber);
                testTransactions.setAddedDate(new Date());
                entityManager.persist(testTransactions);
                entityManager.flush();
          }



      Please explain why there are no records persisted to the db table at the end of persistA() when flush() is called and presumably the transaction is committed.  Maybe it's not committed but I was expecting it would be b/c of the REQUIRES_NEW annotation for the method.


      I need to be able to insert the records prior to any exception being thrown and display error msg's for the ones that failed (after the exception) or more likely were not attempted due to the exception.  In other words, the typical ACID properties (specifically atomicity) don't apply; it's not an all-or-nothing transaction.  I don't want the user to be forced to re-enter a whole bunch of data values in the JSF form for the records prior to the exception.  Is this possible to achieve with Seam/Hibernate/JPA?  If yes, how?  thx.

        • 1. Re: understanding transactions and flushMode=MANUAL
          Arbi Sookazian Master

          stepping thru the debugger (with brkpt at the flush() in question for persistA()), here is the pertinent log output in my hibernate.log up to the line which causes the IndexOutOfBoundsException:



          2009-03-18 16:15:08,688 TRACE [org.hibernate.event.def.AbstractSaveEventListener] executing insertions
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] executing identity-insert immediately
          2009-03-18 16:15:08,688 TRACE [org.hibernate.persister.entity.AbstractEntityPersister] Inserting entity: com.cox.bets.entity.TestTransactions (native id)
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 2)
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.jdbc.ConnectionManager] opening JDBC connection
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.SQL] 
              insert 
              into
                  boBETS.dbo.TestTransactions
                  (addedDate, serialNumber) 
              values
                  (?, ?)
          2009-03-18 16:15:08,688 TRACE [org.hibernate.jdbc.AbstractBatcher] preparing statement
          2009-03-18 16:15:08,688 TRACE [org.hibernate.persister.entity.AbstractEntityPersister] Dehydrating entity: [com.cox.bets.entity.TestTransactions#<null>]
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.id.IdentifierGeneratorFactory] Natively generated identity: 10
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 3)
          2009-03-18 16:15:08,688 TRACE [org.hibernate.jdbc.AbstractBatcher] closing statement
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
          2009-03-18 16:15:08,688 DEBUG [org.hibernate.jdbc.ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 2) (open ResultSets: 0, globally: 0)]
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
          2009-03-18 16:15:22,423 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.cox.bets.entity.TestTransactions
          2009-03-18 16:15:22,423 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.cox.bets.entity.TestTransactions
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.pretty.Printer] listing entities:
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.pretty.Printer] com.cox.bets.entity.TestTransactions{testTransactionsId=10, addedDate=2009-03-18 16:15:08, serialNumber=null}
          2009-03-18 16:15:22,423 TRACE [org.hibernate.jdbc.ConnectionManager] registering flush begin
          2009-03-18 16:15:22,423 TRACE [org.hibernate.jdbc.ConnectionManager] registering flush end
          2009-03-18 16:15:22,423 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection



          I also noticed that somehow (I'm guessing Hibernate does this) the table in sql server db was locked as I simultaneously ran a select statement and it was just hanging in SQL Management Studio (read lock???)


          In a high-transaction system, isn't this a performance problem?  Why should the entire table be locked for a potential insert?  Is this normal and how can we tweak this behavior?  Is this covered in the Bauer/King book?  thx.

          • 2. Re: understanding transactions and flushMode=MANUAL
            Ingo Jobling Master

            The transaction is rolled back because an Exception was thrown.  This is the expected behavior.


            Surround the code between A and B with a try/catch.  In the catch, add exceptions to a list to be displayed to the user. 

            • 3. Re: understanding transactions and flushMode=MANUAL
              Ingo Jobling Master

              Does the long running table lock have anything to do with being paused in debug ;-)