Announcement Announcement Module
Collapse
No announcement yet.
transaction roll back not happening after calling flush Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • transaction roll back not happening after calling flush

    Hi,

    I am using spring 2.5.6 along with hibernate annotationversion 3.4.1.
    Flush mode is AUTO be default.
    I have @transactional method xyz (with all default attributes) like this:

    Code:
    enrichSchedule(scheduleSummary, chargeCycleId,
    					dfChargePlanAssocitaions, sharedRateGroupIds, dfAddedOrUpdatedRates,
    					schedule);
       		Session session = scheduleDao.getSessionFactory().getCurrentSession();
        		session.persist(schedule);
        		
        		scheduleAssociation.setSchedule(schedule);
        		
        		session.persist(scheduleAssociation);
        		
        		session.flush();
     throw new RuntimeException();
    ScheduleDao extends from HibernateDaoSupport class.

    I am explicitly throwing runtime exception wanting the transaction to rollback but it is not happening even though the log says that transaction is rolling back.

    Log extract:
    2009-10-30 18:07:27,040 DEBUG [SQL ]junit :update ChargePlanAssociation set Schedule=? where id=?
    Hibernate: update ChargePlanAssociation set Schedule=? where id=?
    2009-10-30 18:07:27,040 TRACE [LongType ]junit :binding '10000' to parameter: 1
    2009-10-30 18:07:27,040 TRACE [LongType ]junit :binding '10000' to parameter: 2
    2009-10-30 18:07:27,056 DEBUG [SQL ]junit :insert into SCHEDULE_RATEGROUP (Schedule, rateGroup) values (?, ?)
    Hibernate: insert into SCHEDULE_RATEGROUP (Schedule, rateGroup) values (?, ?)
    2009-10-30 18:07:27,056 TRACE [LongType ]junit :binding '10000' to parameter: 1
    2009-10-30 18:07:27,056 TRACE [LongType ]junit :binding '5' to parameter: 2
    2009-10-30 18:07:27,056 DEBUG [SQL ]junit :insert into SCHEDULE_RATEGROUP (Schedule, rateGroup) values (?, ?)
    Hibernate: insert into SCHEDULE_RATEGROUP (Schedule, rateGroup) values (?, ?)
    2009-10-30 18:07:27,056 TRACE [LongType ]junit :binding '10000' to parameter: 1
    2009-10-30 18:07:27,056 TRACE [LongType ]junit :binding '1' to parameter: 2
    2009-10-30 18:07:27,056 DEBUG [SQL ]junit :delete from Formula where id=? and updatedVersion=?
    Hibernate: delete from Formula where id=? and updatedVersion=?
    2009-10-30 18:07:27,071 TRACE [LongType ]junit :binding '2' to parameter: 1
    2009-10-30 18:07:27,071 TRACE [LongType ]junit :binding '22' to parameter: 2
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Participating transaction failed - marking existing transaction as rollback-only
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Setting JDBC transaction [com.ibm.db2.jcc.c.gc@82fba9] rollback-only
    2009-10-30 18:07:27,071 DEBUG [tionTransactionAttributeSource]junit :Adding transactional method [getSessionFactory] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Participating in existing transaction
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Global transaction is marked as rollback-only but transactional code requested commit
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Participating transaction failed - marking existing transaction as rollback-only
    2009-10-30 18:07:27,071 DEBUG [DataSourceTransactionManager ]junit :Setting JDBC transaction [com.ibm.db2.jcc.c.gc@82fba9] rollback-only
    2009-10-30 18:07:27,071 INFO [RateAgentTest ]junit :AUTO
    2009-10-30 18:07:27,087 DEBUG [SpringMethodRoadie ]junit :Test method [public void com.gs.gss.ld.cafe.business.facade.RateAgentTest.t estCreateNewSchedule()] threw exception: null
    2009-10-30 18:07:27,087 DEBUG [sactionalTestExecutionListener]junit :Retrieved @TransactionConfiguration [@org.springframework.test.context.transaction.Tran sactionConfiguration(defaultRollback=true, transactionManager=transactionManager)] for test class [class com.gs.gss.ld.cafe.business.facade.RateAgentTest]
    2009-10-30 18:07:27,087 DEBUG [sactionalTestExecutionListener]junit :Retrieved TransactionConfigurationAttributes [[TransactionConfigurationAttributes@140c973 transactionManagerName = 'transactionManager', defaultRollback = true]] for class [class com.gs.gss.ld.cafe.business.facade.RateAgentTest]
    2009-10-30 18:07:27,087 DEBUG [sactionalTestExecutionListener]junit :No method-level @Rollback override: using default rollback [true] for test context [[TestContext@f7c31d testClass = RateAgentTest, locations = array<String>['classpath*:cafe-config/spring-*-context.xml'], testInstance = com.gs.gss.ld.cafe.business.facade.RateAgentTest@2 acc65, testMethod = testCreateNewSchedule@RateAgentTest, testException = [null]]]
    2009-10-30 18:07:27,087 DEBUG [DataSourceTransactionManager ]junit :Initiating transaction rollback
    2009-10-30 18:07:27,087 DEBUG [DataSourceTransactionManager ]junit :Rolling back JDBC transaction on Connection [com.ibm.db2.jcc.c.gc@82fba9]
    2009-10-30 18:07:27,196 DEBUG [SessionFactoryUtils ]junit :Closing Hibernate Session
    2009-10-30 18:07:27,196 DEBUG [DataSourceTransactionManager ]junit :Releasing JDBC Connection [com.ibm.db2.jcc.c.gc@82fba9] after transaction
    2009-10-30 18:07:27,196 DEBUG [DataSourceUtils ]junit :Returning JDBC Connection to DataSource
    2009-10-30 18:07:27,274 INFO [sactionalTestExecutionListener]junit :Rolled back transaction after test execution for test context [[TestContext@f7c31d testClass = RateAgentTest, locations = array<String>['classpath*:cafe-config/spring-*-context.xml'], testInstance = com.gs.gss.ld.cafe.business.facade.RateAgentTest@2 acc65, testMethod = testCreateNewSchedule@RateAgentTest, testException = [null]]]
    2009-10-30 18:07:27,446 INFO [GenericApplicationContext ] :Closing org.springframework.context.support.GenericApplica tionContext@15ad5c6: display name [org.springframework.context.support.GenericApplica tionContext@15ad5c6]; startup date [Fri Oct 30 18:06:49 GMT+05:30 2009]; root of context hierarchy

    Could anyone please tell me whats wrong here?

  • #2
    My guess you are using MySQL with non-transactional tables.

    Comment


    • #3
      Thanks Marten but I am actually using DB2 and tables very much support transactions. Moreover, if I throw RuntimeException before calling flush, the session state is perhaps rolling back.

      Comment


      • #4
        If you call flush and it is indeed committed my guess is that your transactional configuration is wrong.

        Comment


        • #5
          Marten, my understanding of flush is that it synchronizes session state with db state by executing SQL statements. So if my session object has got its attributes modified, the modifications would be done in db when you call flush. Please correct me if this is not the expected behaviour.

          Regarding the issue in hand, it appears that AUTO flush mode is making changes to db before any "find" query executed and later on in case of any RuntimeException , the changes made to the db are not being rolled back for some reason. I am thinking to change the Flush mode to COMMIT so that the changes to db are only done when transaction commits. Please let me know your thought on this.

          Comment


          • #6
            Marten, my understanding of flush is that it synchronizes session state with db state by executing SQL statements. So if my session object has got its attributes modified, the modifications would be done in db when you call flush. Please correct me if this is not the expected behaviour.
            Well partially you are correct. It synchronizes the state but it is not COMMITTING so changes are only visible to the current transactin you can still rollback.

            Regarding the issue in hand, it appears that AUTO flush mode is making changes to db before any "find" query executed and later on in case of any RuntimeException , the changes made to the db are not being rolled back for some reason. I am thinking to change the Flush mode to COMMIT so that the changes to db are only done when transaction commits. Please let me know your thought on this.
            That flush is called before find/get/load is normal intended behavior. This is done so that the select queries run against the most recent dataset for the current transaction. This is standard hibernate behavior.

            As I stated I suspect that you have a wrong configuration, all you do in your code should still be able to be rolledback even after calling flush...

            Comment


            • #7
              My dao classes extend HibernateDaoSupport and am using getSessionFactory().getSession() for all operations. Also, Dao's are defined with @Repository annotations.
              And there lies your problem. getSession opens a new session and bypasses springs transaction management.

              I suggest don't extends HibernateDaoSupport (or the use HibernateTemplate) as it isn't recommended anymore. Simply inject the sessionfactory and use it directly. However don't use getSession/openSession but use getCurrentSession.

              Could you also post your hibernate.cfg.xml as that might also have some misconfigurations.

              Comment


              • #8
                Oh sorry..actually I am using getSessionFactory().getCurrentSession() actually and not getSessionFactory().getSession() . I guess this wouldnt create a new session everytime.

                Comment


                • #9
                  Your hibernate.cfg.xml is fine.

                  What I don't get is.

                  Code:
                  Session session = scheduleDao.getSessionFactory().getCurrentSession();
                  If you are inside the dao why are you calling getSessionFactory on an instance?!

                  Comment


                  • #10
                    And how/where are your transactions defined? Daos or middletier?

                    Comment


                    • #11
                      middletier and Data access layer both have interfaces as @Transactional with all default attributes.

                      Comment


                      • #12
                        Only your service layer should have @Transactional, try removing it from the persistence layer. If my guess is right you probably will now get exceptions that there is no ongoing transaction (due to the @Transactional on the service layer being ignored).

                        Comment


                        • #13
                          Ok, As you said i removed @Transactional from data access layer.
                          I ran my test case but still the same issue. I did not get the exception- no ongoing transaction.
                          I guess since data access layer is accessed from middle tier and i invoke midlde tier first which basically starts the transaction. The issue still being i could see data inserted into db even after I throw RuntimeException in middletier as the last step.

                          Comment


                          • #14
                            There really must be something wrong with either your whole setup or your testcase. There can only be data in the database if there is a commit, a commit is generated after a method with @Transactional has ended (depending on the configuration). Even if you call flush you can still rollback those changes a flush isn't a commit.

                            Can you strip down a working (well non-working) zip it and put it here (or if you like I can pm you my email).

                            Comment


                            • #15
                              Has anyone encountered a similar issue? Changes are not rollbacked after flush is called.

                              Method is transactional, transaction boundary is defined using AOP transaction advice.

                              In my case flush executes 3 DML statements (1 insert, 2 updates), last update fails due exception from DB trigger. Tried to catch exception and clear & close session, that didn't helped.

                              Code:
                                      if (true) {
                                      	//throw new BatchJobException("Testing rollback"); -- this works and all changes are rollbacked
                                      	try {
                                      		sessionFactory.getCurrentSession().flush();
                                      	} catch (Exception e) {
                                      		sessionFactory.getCurrentSession().clear();
                                      		sessionFactory.getCurrentSession().close();
                                      		throw new BatchJobException("Testing rollback");  -- changes are not rollbacked
                                      	}
                                      }
                              Last edited by maris; Jun 18th, 2013, 11:01 AM.

                              Comment

                              Working...
                              X