Announcement Announcement Module
Collapse
No announcement yet.
No rollback with exceptions using Hibernate Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • No rollback with exceptions using Hibernate

    Hello!

    I'm new to using Spring/Hibernate, so I thank you in advance for your patience =)

    I'm trying to use Spring's transaction management with Hibernate, but when I deploy my Spring / Hibernate app to Tomcat and then throw an exception from within the code, no rollback is occuring. Here's a snippet from my Spring applicationContext.xml file:

    Code:
      <!-- Deposit Manager Beans -->
      <bean id="depositManager" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces"><value>org.dm.daniel.grace.business.DepositManager</value></property>
        <property name="interceptorNames">
          <list>
        <!--    <idref local="depositManagerSecurity"/> -->
            <idref local="transactionInterceptor"/>
            <idref local="depositManagerTarget"/>
          </list>
        </property>
      </bean>
    
      <bean id="depositManagerTarget" class="org.dm.daniel.grace.business.DepositManagerImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    	<property name="logManager"><ref local="logManager"/></property>
      </bean>
    
      <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="transactionAttributes">
          <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
        </property>
      </bean>
    
      <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
      </bean>
    And here is an example of how I'm trying to use this:

    Code:
    	public DepositDTO create&#40;DepositDTO dto&#41; &#123;
    
            // Create a new deposit based on DepositDTO info
    	    Deposit deposit = DTOFactory.getDeposit&#40;dto&#41;;
            // "Ignore" the id field - make it null
            deposit.setId&#40;null&#41;;
    
            // Save the new deposit
            getHibernateTemplate&#40;&#41;.saveOrUpdate&#40;deposit&#41;;
            
            if &#40;0 < 1&#41;
                throw new RuntimeException&#40;"Should cause rollback of new deposit"&#41;;
            
            // Populate newDTO
            DepositDTO newDTO = DTOFactory.getDepositDTO&#40;deposit&#41;;
    
            // * * Logging * *
            String logMsg = "Deposit &#91;" + newDTO.getId&#40;&#41; + "&#93; Created new deposit&#58; " + newDTO; 
            // Write to system log
            logger.info&#40;logMsg&#41;;
    
            return newDTO;
    	&#125;
    This is essentially supposed to create a deposit in the database on the call to saveOrUpdate(), but then "crash" and rollback. It crashes, but no rollback occurs and the new deposit remains in the database.

    For reference, I'm using Hibernate 2.1, MySQL Connector/J 3.1.6, and MySQL server 4.0.23.

    Thanks for any help!!

    ~Tom

  • #2
    Debug it. Check how new session's are created and what actually happens in HibernateTransactionManager on rollback.

    Try using this bean definition instead of ProxyFactoryBean:

    <bean id="basicDAO" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager"><ref local="hibernateTransactionManager"/></property>
    <property name="target"><ref local="basicDAOImpl"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="find*">PROPAGATION_SUPPORTS</prop>
    <prop key="load*">PROPAGATION_SUPPORTS</prop>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="delete*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>

    Comment


    • #3
      Hi! Thanks for your help. Unfortunately, using TransactionProxyFactoryBean is not an option, due to our need of a security interceptor as well.

      I debugged the transaction - here is the complete record:

      Code:
      <log4j&#58;event logger="org.springframework.transaction.interceptor.TransactionInterceptor" timestamp="1107369176526" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Getting transaction for method 'create' in class &#91;org.dm.daniel.grace.business.DepositManager&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="1"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176545" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Bound value &#91;org.springframework.jdbc.datasource.ConnectionHolder@15e601&#93; for key &#91;[email protected]bd&#93; to thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="2"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176545" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Bound value &#91;org.springframework.orm.hibernate.SessionHolder@1af8109&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@6299f7&#93; to thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="3"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176545" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Initializing transaction synchronization&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="4"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176546" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Retrieved value &#91;org.springframework.orm.hibernate.SessionHolder@1af8109&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@6299f7&#93; bound to thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="5"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176577" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Retrieved value &#91;org.springframework.orm.hibernate.SessionHolder@1af8109&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@6299f7&#93; bound to thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="6"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.interceptor.RuleBasedTransactionAttribute" timestamp="1107369176578" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Applying rules to determine whether transaction should rollback on java.lang.RuntimeException&#58; Should cause rollback of new deposit&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="7"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.interceptor.RuleBasedTransactionAttribute" timestamp="1107369176578" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Winning rollback rule is&#58; null&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="8"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.interceptor.RuleBasedTransactionAttribute" timestamp="1107369176578" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;No relevant rollback rule found&#58; applying superclass default&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="9"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.interceptor.TransactionInterceptor" timestamp="1107369176578" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Invoking rollback for transaction on method 'create' in class &#91;org.dm.daniel.grace.business.DepositManager&#93; due to throwable &#91;java.lang.RuntimeException&#58; Should cause rollback of new deposit&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="10"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176579" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Clearing transaction synchronization&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="11"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176580" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Removed value &#91;org.springframework.orm.hibernate.SessionHolder@1af8109&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@6299f7&#93; from thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="12"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      
      <log4j&#58;event logger="org.springframework.transaction.support.TransactionSynchronizationManager" timestamp="1107369176580" sequenceNumber="0" level="DEBUG" thread="Thread-0">
      <log4j&#58;message><!&#91;CDATA&#91;Removed value &#91;org.springframework.jdbc.datasource.ConnectionHolder@15e601&#93; for key &#91;[email protected]bd&#93; from thread &#91;http-8081-Processor22&#93;&#93;&#93;></log4j&#58;message>
      <log4j&#58;throwable><!&#91;CDATA&#91;
      &#93;&#93;></log4j&#58;throwable>
      <log4j&#58;locationInfo class="?" method="?" file="?" line="?"/>
      <log4j&#58;properties>
          <log4j&#58;data name="hostname" value="file"/>
          <log4j&#58;data name="log4jid" value="13"/>
          <log4j&#58;data name="application" value="file&#58;///usr/local/share/jakarta-tomcat-5/logs/grace/all.log"/>
      </log4j&#58;properties>
      </log4j&#58;event>
      Now, much of that is Greek to me, but it seems that everything *should* be working okay, based on the stuff in the "messages". In fact, if I didn't then look at the database, I'd assume it *was* okay. But in the database, the inserted values are still there (not rolled back.)

      Any other thoughts?

      Comment


      • #4
        What table type in MySQL?

        Are you using the InnoDB table type in MySQL? I haven't used MySQL in a looooong time, before InnoDB was added, but I have read several times that the other table type (MyISAM) doesn't have a key feature that InnoDB adds. And if I recall correctly, it's tollback capability / transaction support.

        [ Yay! Looks like my memory's in good shape. Check this thread for confirmation. ]

        Clearly from the logs, Spring is trying to roll back the transaction. Another thing you could try is use P6Spy or some other JDBC logging facility to see if Hibernate is calling rollback() on the Connection. If it is, then it's definitely MySQL or the JDBC driver.
        Last edited by robyn; May 19th, 2006, 05:59 AM.

        Comment


        • #5
          Right on!

          You're right on with that. I hadn't even thought about the table type mattering. When I change them to InnoDB, it worked instantly. Many thanks!

          Comment

          Working...
          X