Thursday, May 1, 2014

Spring Transaction Management

Understanding transactions: 

 Lets say i would like to transfer 1000 rupees from my savings account to current account.If every thing goes well my 1000 rupees will be debited from savings account and it will be credited into my current account.What if my money debited but not credited into my current account? I am at loss right? So these actions should be wrapped in a transaction. A transaction is basically a unit of work, its "all or nothing".So if some problem happens when crediting the amount, the transaction should be rolled back as if these actions never happened.

A transaction is characterized by 4 properties

1)Atomic:Transactions are made of one more actions bundle into a single unit of work.Its all or nothing. Transaction will be successful only if all actions completed successfully otherwise transaction will be rolled back as if nothing has happened.
2)Consistent: Once the transaction completed whether successfully or it was rolled back, the database should be in a consistent state no matter how many transactions happening concurrently. If a transaction triggers secondary actions like CASCADE and TRIGGERS those actions should also successful or the transaction fails.
3)Isolation: In a multi threaded environment, multiple users will do different transactions concurrently.Isolation specifies when and how the changes implemented in an operation visible to other parallel operations. Transactions should be isolated from each other, preventing concurrent reads and
writes to the same data from occurring. (Note that isolation typically involves locking rows and/or tables in a database.)
4)Durability: Once the transaction has completed, the results of the transaction made permanent so that they survive any sort system crash.This involves storing the data in databases.

Coming to Spring transaction management, Spring offers both programmatic transaction management and declarative transaction management.

In this post, i will explain about the declarative transaction management.

Whether we are using programmatic transaction management or declarative transaction management we need a Spring transaction manager to interface with a platform specific transaction implementation so that we are free from dealing directly  with platform specific transaction implementations.

Depends on underlying persistent mechanisms Spring supports different transaction managers.

below are some of them

1)HibernateTransactionManager
2)JdoTransactionManager
3)JtaTransactionManager

Since my application persistence handled by Hibernate i am going to explain Spring Declarative Transaction Management using HibernateTransactionManager.I am explaining using the annotation base declarative transaction management

We need to define the Spring's tx namespace and to use the @Transactional annotation.

sample tx namespace declaration in spring application context

http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

defining HibernateTransactionManager in application context xml

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

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


The sessionFactory should be wired with HibernateSessionFactory.The HibernateTransactionManager delegates responsibility for transaction management to and org.Transaction object that it retrives from Hibernate session.If the transaction successfully completes it will call the commit() on the Transaction object,otherwise it will rollback() on the Transaction object.

In Spring declarative transactions are defined with transaction attributes.These attributes define how a transaction policies should be applied to a method.

These are
1)Propagation
2)Isolation
3)Read-only
4)Timeout
5)Rollback rules

Lets see what these attributes are up to

1)Propagation: Propagation rules defines the transaction boundaries.Spring provides several rules to choose from

a)PROPAGATION_NEVER: When we annotate our business method  @Transactional with PROPAGATION_NEVER, it means this method shouldn't run in a transaction context.If an existing transaction is in progress then an exception will be thrown.

b)PROPAGATION_MANADATORY: Indicates that the method must run with in a transaction.Other wise an exception will be thrown.

c)PROPAGATION_REQURIED: Indicates that the method must run with in a transaction.If an existing transaction is not there then a new transaction will be started.

d)PROPAGATION_NESTED: Indicates that the method must run with in an nested transaction if an existing transaction is in progress. The nested transaction can be committed or roll back individually from the enclosing transaction.If no existing transaction is present then it will behave like PROPAGATION_REQUIRED.So a new transaction will be started.

e)PROPAGATION_REQUIRES_NEW: Indicates that the current transaction must run with in its own transaction.A new transaction will be started if an existing transaction in progress, the existing transaction will be suspended until this transaction completes.

f)PROPAGATION_SUPPORTS: Indicates that the current method doesn't required a transnational context but will supports if an existing transaction in progress.

2)ISOLATION LEVELS:

Isolation levels defines how much a transaction will be impacted by the other concurrent transactions.

In a enterprise application, its possible that many transaction happens concurrently.While this is necessary we may lead to the following problems

1)Dirty Reads: Lets say we have Transaction A and Transaction B.Imagine if transaction A reads the data and update the data but not committed the changes.Now Transaction B comes in and read the data and later Transaction A rolled back these changes.The data that Transaction B read is invalid now.This is called the Dirty Reads.

2)Nonrepeatable Reads: Lets say Transaction A reads a row in the table.Now Transaction B came and it reads the same record, mean while Transaction A updates the same record.If Transaction B reads the same record again Transaction B gets a different data.This is called Non Repeatable Read problem.

3)Phantom Reads: This is similar to Non Repeatable Read problem. These occur when a transaction A reads several rows, and then a concurrent transaction B inserts rows. Upon subsequent queries, the first transaction A finds additional rows that weren’t there before.

In an ideal situation, the transaction completely isolated from other transaction.But this certainly have a dent on the application as this perfect isolation require locks on the record or complete table on the database.
Since not operations require perfect isolation levels we can flexible with regard to the transaction isolation level.Spring supports the following transaction isolation levels.

a) ISOLATION_DEFAULT:This will use the underlying isolation level of the database.

b)ISOLATION_READ_UNCOMMITTED: Allows a transaction to read uncommitted data by another transaction.This may result in dirty reads, nonrepeatable reads and phantom reads.

c)ISOLATION_READ_COMMITTED: Allows a transaction to read only committed data.But may result in nonrepeatable reads and phantom reads.

d)ISOLATION_SERIALIZABLE: This is more strict of all these isolation levels.This will restrict dirty reads,non repeatable read and phantom reads.But this will be the slow the performance of the application as it needs to have a lock on the table.


3)READ ONLY: 

This transaction attribute can be applied to methods that you are intended to read some data.

E.g.: You are just presenting few employees data to the end user.No updates required on these records(Read Only).

When you declare this attribute, it may be possible that the underlying datasource may apply some performance optimizations.Furthermore, if you’re using Hibernate as your persistence mechanism, declaring
a transaction as read-only will result in Hibernate’s flush mode being set to FLUSH_NEVER. This tells Hibernate to avoid unnecessary synchronization of objects with the database, thus delaying all updates until the end of the transaction.

4)TRANSACTION TIMEOUT: If our application need to perform well, each transactions shoudn't take longer time to finish execution. Because transactions may involve locks on the underlying data store, long-running transactions can hold database resources unnecessarily.Instead of waiting the long running transaction finish, we can declare each transaction time out period.

5)Rollback rules:  Spring provides configuration to which exception to rollback a transaction and which doesn't require a rollback.By default transactions rollback for unchecked(Runtime) exceptions but not for checked exceptions.But you can declare a rollback for checked exceptions as well as unchecked exceptions.

Now we have a minimum understanding of how the @Transactional need to be configured lets configure a sample deposit method.

@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
public long deposit(long amount){
private long balance;
.//implementation

return balance;
}

See this link for @Transactional best practices.

http://stackoverflow.com/questions/1079114/spring-transactional-annotation-best-practice

That's all about Spring declarative transaction management...

Thanks for visiting my blog!!!!!!!!

No comments:

Post a Comment