Spring Transaction Management

The Spring Framework provides a consistent abstraction for transaction management that delivers the following

Benefits of using Spring Transaction Management:

  1. Provides a consistent programming model across different transaction APIs such as JTA, JDBC, Hibernate , JPA, and JDO.
  2. Supports declarative transaction management.
  3. Provides a simpler API for programmatic transaction management than a number of complex transaction APIs such as JTA.
  4. Integrates very well with Spring’s various data access abstractions.

The TransactionDefinition interface specifies:

  1. Isolation: the degree of isolation this transaction has from the work of other transactions. For example, can this transaction see uncommitted writes from other transactions.
  2. Propagation: normally all code executed within a transaction scope will run in that transaction. However, there are several options specifying behavior if a transactional method is executed when a transaction context already exists: for example, simply continue running in the existing transaction (the common case); or suspending the existing transaction and creating a new transaction.
  3. Timeout: how long this transaction may run before timing out (and automatically being rolled back by the underlying transaction infrastructure).
  4. Read-only status: a read-only transaction does not modify any data. Read-only transactions can be a useful optimization in some cases (such as when using Hibernate).

We must define a JDBC DataSource, and then use the Spring DataSourceTransactionManager, giving it a reference to the DataSource.

<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>

The related PlatformTransactionManager bean definition will look like this:

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

If We used JTA in a J2EE container, as in the ‘dataAccessContext-jta.xml’ file from the same sample application, we use a container DataSource, obtained via JNDI, in conjunction with Spring’s JtaTransactionManager. The JtaTransactionManager doesn’t need to know about the DataSource, or any other specific resources, as it will use the container’s global transaction management infrastructure.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- other <bean/> definitions here -->
</beans>

We can use Hibernate local transactions easily, as shown in the following examples from the Spring Framework’s PetClinic sample application. In this case, we need to define a Hibernate LocalSessionFactoryBean, which application code will use to obtain Hibernate Session instances.

The DataSource bean definition will be similar to the one shown previously . If the DataSource is managed by the JEE container it should be non-transactional as the Spring Framework, rather than the JEE container, will manage transactions.

The ‘txManager’ bean in this case is of the HibernateTransactionManager type. In the same way as the DataSourceTransactionManager needs a reference to the DataSource, the HibernateTransactionManager needs a reference to the SessionFactory.

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>org/springframework/samples/petclinic/hibernate/petclinic.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>

With Hibernate and JTA transactions, we can simply use the JtaTransactionManager as with JDBC or any other resource strategy.

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

This is identical to JTA configuration for any resource, as these are global transactions, which can enlist any transactional resource

Resource synchronization with transactions

It should now be clear how different transaction managers are created, and how they are linked to related resources which need to be synchronized to transactions (for example DataSourceTransactionManager to a JDBC DataSource, HibernateTransactionManager to a Hibernate SessionFactory, and so forth). However of how the application code, directly or indirectly using a persistence API (such as JDBC, Hibernate, and JDO), ensures that these resources are obtained and handled properly in terms of proper creation/reuse/cleanup and trigger (optionally) transaction synchronization via the relevant PlatformTransactionManager.

Low-level approach

At a lower level exist classes such as DataSourceUtils (for JDBC), SessionFactoryUtils (for Hibernate), PersistenceManagerFactoryUtils (for JDO), and so on. When it is preferable for application code to deal directly with the resource types of the native persistence APIs, these classes ensure that proper Spring

Framework-managed instances are obtained, transactions are (optionally) synchronized, and exceptions which happen in the process are properly mapped to a consistent API.

For example, in the case of JDBC, instead of the traditional JDBC approach of calling the getConnection() method on the DataSource, you would instead use Spring’s org.springframework.jdbc.datasource.DataSourceUtils class as follows:

Connection conn = DataSourceUtils.getConnection(dataSource);

Declarative transaction management

The Spring Framework’s declarative transaction management is made possible with Spring AOP, although, as the transactional aspects code comes with the Spring Framework distribution and may be used in a boilerplate

fashion, AOP concepts do not generally have to be understood to make effective use of this code. The main difference is that there is no longer any need to configure TransactionProxyFactoryBean beans.

  


Mathematics, Technology and Programming are my passion. I am a part of Java Ecosystem and through this blog, I contribute to it. I am here to blog about my interests, views and experiences. I am on Google+ and Facebook. I feel proud to be listed as a "National Memory Record Holder" in the Limca Book of Records, 2009 and have attempted for an International Memory record in the Guiness Book of Records. I can remember the value of PI upto 10,000 digits after the decimal (3.1415.....). You can contact me on javagenious.com(At)gmal.com ; I would like to hear from you :)

Share This Post

Recent Articles

Powered by WordPress · Designed by Theme Junkie
You might also likeclose