8 Replies Latest reply on May 15, 2009 11:31 PM by gonorrhea

    Entity Manager rollback

    oyesiji77

      I am using the entitymanager in my seam application, in a particular method i have this




           @Transactional(TransactionPropagationType.REQUIRED)
            public void saveNewMember(A a,B b,C c){
                 entityManager.persist(a);
                    entityManager.persist(b);
                    entityManager.persist(c);
            }
      



      I discovered that when an error occurs in c, the record inserted in a does not get Rolled Back, Please how do I accomplish this

        • 1. Re: Entity Manager rollback
          cpopetz

          If there is already a transaction present for the thread in question when this method is entered, it will just use that transaction, and won't roll it back when an exception occurs within the method.  You can use REQUIRES_NEW if you want to be sure there is a new transaction in place that can be rolled back if the method terminates because of an exception.

          • 2. Re: Entity Manager rollback
            sherkan777

            I don't think Clint, that it's good way to create nested transactions.

            • 3. Re: Entity Manager rollback
              cpopetz

              Transactions created with REQUIRES_NEW aren't nested, the existing transaction is suspended for the lifetime of the new transaction.  And I'll guess you'll have to define good.  Certainly there are use cases where one should and shouldn't use REQUIRES_NEW, and it's not supported by all JTA implementations.  But it is part of the EJB 3.0 Spec, and there are places where it makes sense.


              I don't use it because I use POJO transactions and they don't support it :)

              • 4. Re: Entity Manager rollback
                oyesiji77

                Thanks for the Reply under TransactionPropagationType we don't have REQUIRES_NEW, There are only four Options

                • 5. Re: Entity Manager rollback
                  cpopetz

                  Ahh, my fault, I looked to quickly at your code.  You're using Seam Managed Transactions with the @Transactional attribute, not EJB transactions, so you are correct, you don't have access to REQUIRES_NEW.


                  What should happen is that if your method didn't start the tx, but it throws an exception, the Seam interceptor stack will mark the seam transaction as rollback-only, and when the stack unwinds to whatever started the transaction it will then rollback the transaction.


                  So if you truly need rollback as soon as the method exits, then you need to find out what is starting the transaction above you, and arrange for it not to do so.


                  -Clint

                  • 6. Re: Entity Manager rollback
                    oyesiji77

                    Please can someone give me an Answer here, I have tried everything, I started the Conversation using

                    begin-conversation flush-mode="manual"



                    and according to what i read , changes would not be made to the Database until flush is called. but surprisingly after each persist statement , changes are made

                    • 7. Re: Entity Manager rollback
                      cpopetz
                      Setting flush-mode="manual" means it won't _flush_ automatically.  It doesn't mean that things won't be written to the db at all until then though. When you em.persist(), and you have a db-generated identity, hibernate has to write to the db to discover the id.
                      • 8. Re: Entity Manager rollback
                        gonorrhea

                        Popetz is correct (read SiA book to verify his statement regarding using IDENTITY column vs. SEQUENCE column).


                        Here's an excerpt from pg. 377:


                        HIBERNATE’S MANUAL FLUSH MODE
                        Hibernate’s MANUAL flush mode ensures that the persistence context is only flushed
                        when a call is made to the flush() method on the persistence manager API (beanmanaged
                        flushing). This mode gives you the flexibility to take your persistence context
                        in and out of transactions as you please without risking a premature flush.
                        If the entity identifier is generated during an insertion (i.e., auto-increment
                        column), then even with manual flushing, a flush occurs after a call
                        to persist(). This is necessary since each managed entity in the persistence
                        context must be assigned an identifier. To avoid the flush, you
                        need to set the id-generation strategy to sequence (not identity).



                        You will either have to starting using Oracle with sequences, for example, or revert to JDBC/sprocs or similar perhaps (and I'm not sure if that will solve your problem btw).


                        Yes, either option sucks, but it also sucks that MSSQL (what we use) does not offer sequences...