Spring Transactions Primer

What is a Transaction?

Transaction is an activity or group of activities that are performed as a single unit of work. The characteristic of a transaction is that either all the activities that are part of the transaction are performed or none are performed. In other words, even if one of the activity fails then all other activities are cancelled and the system comes back to the state it was in when the transaction was started. This can be best explained by an example. Lets say you are planning on a vacation to a beautiful island and you pick up a nice looking resort. You call them up and book a room. To confirm your booking, you need to transfer money to their account. Transferring money from your account to their account is considered a transaction and these are the two activities that happen in that transaction.

  • Money is debited from your account
  • Money is credited to the resorts account

Both activities are required to make sure that the transaction is complete. If you money is withdrawn and some problem occurs in the system then the transaction is cancelled and the money is credited back to your account and you can try it all over again.

Characteristics of a transaction (ACID)

The software industry coined the acronym ACID for characteristics that a transaction must have. ACID stands for Atomic, Consistent, Isolated and Durable

  • Atomic – Atomic says that either all activities of the transaction occur or none occur. i.e. even if one of the activity in the group fails that the other activities are cancelled (rolled back)
  • Consistent – Once the transaction is complete the system is put back into a state that is properly defined. In our example, if the money were to be debited from your account and not credited to the resorts account then the system is not in consistent state since the money is now lost from the system. From a database point of view, consistent also means that all times none of the database constraints are violated. So even if you do not commit a transaction, at no point should a foreign key constraint or unique key constraint be violated
  • Isolated – The transaction allows multiple people to work on the same data in a way that one transaction does not affect the data of the rest of the system. Therefore, two transactions can occur simultaneously without dirty reads. This is generally accomplished by locking the rows of the database or the database table
  • Durable – The changes of the transaction are persisted to a permanent storage.

Transaction Strategies

Transaction strategies define how you want to implement transactions in your applications. There are mainly three ways to implement a transaction:

  • Local Transactions
  • Programmatic Implementation using Spring Transaction Managers and Transaction Templates
  • Declarative Implementation in the Spring Application XML or using Annotations

In the case of
local transactions
the transaction is managed at the database level or the message provider level. Typically for JDBC this is achieved by setting the
connection.setAutoCommit(false)
before the beginning of the database calls and calling
connection.commit()
at successfull completion of all activities or calling
connection.rollback()
if an exception is thrown. In Spring the connection can be obtained using
DataSourceUtils.getConnection(dataSource)

There are certain limitations to using the low level method. If the code within the setAutoCommit(false) and commit() delegates some activities to another method (say another DAO), then the only way to continue the transaction is to pass you instance of the connection to that Dao. This is not a good design strategy. Also, the low level method is prone to human errors (developers forgetting to commit or demarcate the transaction region). Also it does not work for transactions accross multiple databases or systems (e.g. database and message provider)

In Programmatic transaction the user does not have to work at the connection level. The actual work of managing connections is delegated to the transaction provider and the user only has to manage the transactions. Declarative transactions use the power of spring in defining the transactions in the xml file or through annotations. We discuss programmatic transactions in this tutorial and declarative transactions in this tutorial.

Important Classes in the Spring Transaction API.

It would be good to know the basic classes of the spring transaction API before we go into the actual implementation. We cover some basic classes here, look at the java docs for more details. (or the source code!)

  • org.springframework.transaction.PlatformTransactionManager – This is the main class of the transaction API. It defines methods such as getTransaction(TransactionDefinition definition), commit(status) and rollback(status). The main implementors of these interface are JtaTransactionManager and DataSourceTransactionManager. To implement this interface it is advisable to extend the abstract class AbstractPlatformTransactionManager
  • org.springframework.transaction.support.AbstractPlatformTransactionManager – This abstract class implements the spring transaction workflow. It performs the following workflow operations – determine if there is existing transaction, apply propagation, suspend or resume transactions, perform rollback modifications.
  • org.springframework.jdbc.datasource.DataSourceTransactionManager – This is the concrete implementation of the PlatformTransactionManager via the AbstractPlatformTransactionManager for a JDBC datasource. It binds a JDBC datasource to the current thread. Note that the application code needs to retrieve the connection using DataSourceUtils.getConnection(DataSource) instead of DataSource.getConnection(). Spring’s JdbcTemplate does this implicitly. However, if you have to use DataSource.getConnection() then wrap the datasource in TransactionAwareDataSourceProxy and pass that in the Dao to allow for spring managed trasactions. This transaction manager supports custom isolation levels and timeouts. Use this only for non-XA datasources.
  • org.springframework.transaction.jta.JtaTransactionManager – This is the JTA implementation of the PlatFormTransactionManager. It delegates the transaction management to a JTA provider. Use this transaction manager for distributed transactions
  • org.springframework.orm.hibernate4.HibernateTransactionManager– This is the concrete implementation of the PlatformTransactionManager for a single hibernate SessionFactory. It associates a hibernate session from the specified factory to a thread.
  • Leave a Comment