Announcement Announcement Module
No announcement yet.
@Transactional not producing a roll back Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transactional not producing a roll back

    I am trying to understand the use of declarative transaction management, but my demo is not rolling back after a DataAccessException.

    From applicationContext.xml
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value=""/>
            <property name="url" value="jdbc:sqlserver://localhost;databaseName=emscribedx;"/>
            <property name="username" value="..."/>
            <property name="password" value="..."/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	 <property name="dataSource" ref="dataSource" />  
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"  />
    This method should demonstrate a rollback of the changes to recOne when recTwo contains values that produce a DataAccessException.

    public void updateTwoRecords ( HistoricalDate recOne, HistoricalDate recTwo ){
    The log shows that Spring located this method and registered it as Transactional
    2605 [main] DEBUG org.springframework.transaction.annotation.Annotat ionTransactionAttributeSource - Adding transactional method 'updateTwoRecords' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''

    However, what I see is that the changes from first update will still be committed when the second fails.

    From my log. This is the current status of the two records in the DB before testing begins.
    ============= EventOne Read Back Before method call that should trigger a rollback ===============id=19 date=2008-09-10 event=Original Event One Replaced by this
    ============= EventTwo Read Back Before method call that should trigger a rollback ===============id=20 date=1846-09-10 event=Original Event Two Replaced by this

    These are the values of the two objects in memory before passing them to the updateTwoRecords method.
    ============= EventOne Before method call that should trigger a rollback ===============id=23 date=2008-09-10 event=Large Hadron Collider powered up
    ============= EventTwo Before method call that should trigger a rollback ===============id=24 date=1846-09-10 event=First patent issued for sewing machine XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    When the updateTwoRecords() method is called this is logged by the second update.
    org.springframework.dao.DataIntegrityViolationExce ption: PreparedStatementCallback; SQL [update historical_dates set date = ? ,event = ? where id=?]; String or binary data would be truncated.; nested exception is String or binary data would be truncated.

    values read from the DB after the call to updateTwoRecords. The changes to EventOne have not been rolled back.
    ============= EventOneReadBack After Error ===============id=13 date=2008-09-10 event=Large Hadron Collider powered up
    ============= EventTwoReadBack After Error ===============id=14 date=1846-09-10 event=Original Event Two Deleted

    I'm guessing that I'm missing some configuration information. I see in ch 10 of the Spring docs that the config file contains a <tx:advice> element and an <aop:config> element. But I don't see this in numerous examples from the web.

    What is missing or what am I doing wrong?


  • #2
    Here's the answer you helpless dweeb!

    I hate it when I have to answer my own question! I just want to sit back and let all of my problems be solved by the great minds at SpringSource. But in this case there were no quick answers so I continued to search for an answer by re-reading all of the pages that were produced by a Google search for "Spring transactional rollback".

    Evenually it dawned on me that the problem was probably in the code I had no control over, the service that was handling the actual DB inserts and updates. When I took a look the answer was obvious, the service was catching DataAccessException and not re-throwing it. So Spring never saw the exception and, correctly, did not do a roll back. When I modified the insert/update methods to re-throw DataAccessException rollbacks happened as expected.

    	} catch (DataAccessException e) {
    		appLogger.error(myName + " insert() threw a DataAccessException after this sql->" + insertSql );
    		e.printStackTrace() ;
    		// rethrow so Spring will roll back at the caller
    		throw new RuntimeException(e);
    If you came to this page with a similar problem, i.e. rollbacks not happening when you expect them to happen, caught exceptions may be your problem. I would suggest that you start at the insert/update and work 'upwards' to make sure that a RuntimeException will propagate back to the method that is annotated with @Transactional.

    I also suggest that you set the logging level to DEBUG so that you can see what Spring is doing. Hopefully, you will eventually see the lovely message:

    3215 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Initiating transaction rollback