Spring Framework - Transaction with Hibernate

Spring Transaction Configuration

Define a Data source

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
</bean>

Transaction Configuration

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

Using JNDI for datasource

<beans ...>
  <jee:jndi-lookup id="dataSource" jndi-name="jdbc/mydatastore"/> 

  <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
  
</beans>

WebLogic Server 9.0 or above, use WebLogicJtaTransactionManager instead of JtaTransactionManager

Declarative Transaction Management

<beans ...>
  

  <tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="get*" read-only="true"/>
    <tx:method name="*"/>
  </tx:attributes>
  </tx:advice>
  
  <bean id="userService" class="com.innotrekker.app.UserService"/

  <aop:config>
  <aop:pointcut id="userService" expression="execution(* com.innotrekker.app.UserService.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="userServiceOperation"/>
  </aop:config>
  
  <!-- don't forget the DataSource -->
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
  <property name="url" value="jdbc:oracle:thin:@127.0.0.1:mydb"/>
  <property name="username" value="myuser"/>
  <property name="password" value="password"/>
  </bean>

  <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
  </bean>

</beans>

Different Transaction Configuration

  <aop:config>

    <aop:pointcut id="defaultService"
          expression="execution(* com.innotrekker.app.*Service.*(..))"/>

    <aop:pointcut id="noTxService"
          expression="execution(* com.innotrekker.notx.*Service.*(..))"/>

    <aop:advisor pointcut-ref="defaultService" advice-ref="defaultTxAdvice"/>

    <aop:advisor pointcut-ref="noTxService" advice-ref="noTxAdvice"/>

  </aop:config>

  <bean id="userService" class="com.innotrekker.app.UserService"/>

  <bean id="logService" class="com.innotrekker.notx.LogService"/>

  <tx:advice id="defaultTxAdvice">
    <tx:attributes>
      <tx:method name="get*" read-only="true"/>
      <tx:method name="*"/>
    </tx:attributes>
  </tx:advice>

  <tx:advice id="noTxAdvice">
    <tx:attributes>
      <tx:method name="*" propagation="NEVER"/>
    </tx:attributes>
  </tx:advice>

Setup rollback condition

  <tx:method name="*" rollback-for="Throwable" no-rollback-for="SomeHarmlessException"/>

Transaction Annotation

@Transactional
public class UserService implements UserService {

}

Spring Transaction Annotation Configuration

  <bean id="userService" class="com.innotrekker.app.UserService"/>

  <tx:annotation-driven transaction-manager="txManager"/>

  <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
  </bean>

Multiple Transaction Manager

public class UserService {
  
    @Transactional("tx1")
    public void op1(...) { ... }
  
    @Transactional("tx2")
    public void op2(...) { ... }
  }
 <tx:annotation-driven/>

  <bean id="transactionManager1" class="org.springframework.jdbc.DataSourceTransactionManager">
    ...
    <qualifier value="tx1"/>
  </bean>

  <bean id="transactionManager2" class="org.springframework.jdbc.DataSourceTransactionManager">
    ...
    <qualifier value="tx2"/>
  </bean>  

Hibernate Configuration

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mappingResources">
  <list>
    <value>com/innotrekker/app/user.hbm.xml</value>
  </list>
  </property>
  <property name="hibernateProperties">
    <value>
      hibernate.dialect=${hibernate.dialect}
    </value>
  </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
</bean>

if Container JTA is used

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

Using Hibernate SessionFactory

public class UserDaoImpl implements UserDao {

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Collection loadUsers() {
        return this.sessionFactory.getCurrentSession()
                .createQuery("from users")
                .list();
    }
}
<beans>
  <bean id="userDao" class="com.innotrekker.app.UserDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>
</beans>

Declarative Transaction

  <bean id="transactionManager" 
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
  </bean>
  
  <aop:config>
    <aop:pointcut id="userServiceMethods" 
            expression="execution(* com.innotrekker.app.UserService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="userServiceMethods"/>
  </aop:config>

  <tx:advice id="txAdvice" transaction-manager="myTxManager">
    <tx:attributes>
      <tx:method name="get*" propagation="REQUIRED"/>
    </tx:attributes>
  </tx:advice>

  <bean id="userService" class="com.innotrekker.app.UserService">
    <property name="userDao" ref="userDao"/>
  </bean>
    @Transactional
    public void getUsers() {
        ...
    }