1.Overview

In this tutorial, we will cover what is the transaction and its properties (ACID). Further, we will discuss the spring declarative transaction management and about the @Transactional annotation and its attributes include isolation, propagation and more.

2.What is the transaction and its properties?

The transaction is a unit of work that reads or updates the contents of a database. The transaction follows ACID properties to maintain consistency in the database. the transaction properties are Atomicity, Consistency, Isolation, and Durability.

Atomicity: all or none

Either all operations of the transaction should properly reflect in a database or none are.

Consistency: After the transaction commits, data should be in consistency state logically.

Isolation: Transactions should not affect each other.

Durability: The committed data should not lose by any system failure.

3. Spring transaction management

Spring supports two types of transaction management. They are
1.Programmatic transaction management
2.Declarative transaction management

3.1 Programmatic transaction management:

Here, we have to manage transactions with the help of programming. It gives us extreme flexibility, but it is difficult to maintain.

3.2 Declarative transaction management:

Here, Transaction logic separated from business code. We will manage transactions by using XML or annotation-based configuration.

Choosing programmatic or declarative transaction management depends on your application needs. if the application has less numbers of transactional operations, programmatic transaction management is a good approach and use declarative transaction management in case the application has numerous transactional operations. It is easy to configure and keeps transaction management out of business logic.
In this tutorial, we will only cover the declarative transaction management part.

4. Spring Declarative Transaction management

To start using @Transactional in the spring web application, we should add the required configuration in the spring context file.

4.1 Hibernate Transaction manager configuration:

XML based configuration is

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

<bean id="txManager"
     class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <!-- (this dependency is defined somewhere else) -->
    <property name="sessionFactory" ref= "sessionFactory" />
</bean>

Annotation-based configuration is

Add @EnableTransactionManagement annotation to the @Configuration class and set session factory to transaction manager.

@Configuration
@EnableTransactionManagement
public class HibernateConfiguration {
 
    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(s);
        return txManager;
    } 
}

Configurations for other transaction manager are

DataSource Transaction manager:   

<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   <!-- (this dependency is defined somewhere else) -->
    <property name="dataSource" ref= "datasource" />
</bean>

JPA Transaction manager:

<bean id="txManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
  <!-- (this dependency is defined somewhere else) -->  
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

4.2 @Transactional

@Transactional can be used before the interface definition, a method in the interface, a class definition, or a public method in a class. Spring says annotate a concrete class or the method of a concrete class with @Transactional annotation. If you are using interface-based proxies, then you can annotate the interface with @Transactional annotation.

If you want some methods in a class that is annotated with @Transactional to have different transaction settings. Then to override class-level transaction settings, apply the @Transactional annotation at the method level.

5. @Transactional attributes

@Transactional supported attributes are isolation, noRollbackFor, noRollbackForClassName,propagation,readOnly,rollbackFor, rollbackForClassName , timeout and more.

5.1 readOnly and timeout

ReadOnly attribute default value is false. we can set true for readOnly attribute if the transaction is effectively for read only. Tx manager uses this attribute for corresponding runtime optimization.

Syntax: @Transactional(readOnly=true)

The timeout attribute value is default to the underlying database transaction timeout. By using this attribute, we can specify the transaction timeout.

Syntax: @Transactional (timeout = 10)

5.2 rollbackFor and rollbackForClassName

By default, the transaction will get rollback on  RuntimeException and Error but not on the checked exceptions. If you want rollback transaction when checked exception raise, we can configure transaction rollback on checked exceptions by using these attributes.

@Transactional (rollbackForClassName="NumberFormatException","FileNotFoundException"})
@Transactional(rollbackFor= {NumberFormatException.class,FileNotFoundException.class})
@Transactional(rollbackFor= NumberFormatException.class)
@Transactional(rollbackForClassName="NumberFormatException")

5.3 noRollbackFor and noRollbackForClassName

noRollbackFor and noRollbackForClassName attributes are to configure exception classes which must be sub classes of Throwable on which transaction rollback should not happen.

@Transactional(noRollbackForClassName="NumberFormatException","FileNotFoundException"})
@Transactional(noRollbackFor= {NumberFormatException.class,FileNotFoundException.class})
@Transactional(noRollbackFor= NumberFormatException.class)
@Transactional(noRollbackForClassName="NumberFormatException")

5.4 isolation

Isolation is one of the transaction ACID property. Before we are going to discuss isolation levels, we will have brief idea of database common problems like dirty read, non-repeatable reads, and phantom reads.

Dirty read:

Spring Declarative transaction management dirty read

 

Non-repeatable reads:

Spring Declarative transaction management non repeatable reads

Phantom reads:

Spring Declarative transaction management phamtom reads

Transaction tx1 reads users who have age more than 20 years. Tx2 insert or remove users which fall under tx1 read criteria. Later tx1 reads again users who have age more than 20 years and now it will get different sets of data. This is called phantom reads problem.

 Isolation attribute default value is default to underlaying database default settings.

The below table of information shows isolation value and its respective problems that may occur.

isolation levels

Syntax:  @Transactional (isolation=Isolation.READ_COMMITTED)

5.5 Propagation

The propagation attribute is used to define how the business methods should place in the transaction. Propagation attribute supports REQUIRED, REQUIRES_NEW, SUPPORTS, MANDATORY, NOT_SUPPORTED, NEVER and NESTED. Default propagation is REQUIRED. Remember some transaction managers do not support some propagations.

Syntax: @Transactional (propagation=Propagation.REQUIRED_NEW)

REQUIRED:

 This propagation value says if already transaction exists in the method execution context, code will use it otherwise new transactions will be created.

@Transactional (propagation=Propagation.REQUIRED)               
Public void method1() {   
   //here calling inner method
}


@Transactional (propagation=Propagation.REQUIRED)               
Public void method2() {

}

Here we are method2 of B class in method1 of A class. When execution comes to method1, there is no transaction available.so it creates a new transaction. In the case of method2, the transaction is available which is created at method1 and it will use the same because its propagation level is REQUIRED. That’s why if any runtime exception occurs at method2 will roll back the transaction which is created at method1.

Note:  if method1 and method2 belong to the same class. In that situation, the @Transactional setting will not apply to method2 even though @Transactional present and method1 transaction boundaries only apply for method2.

REQUIRES_NEW:

This propagation value says always create new transactions every time.

@Transactional (propagation=Propagation.REQUIRED)               
Public void method1() {   
   //here calling inner method
}

@Transactional (propagation=Propagation.REQUIRED_NEW)               
Public void method2() {
}

If an exception occurs in method2 will not rollback method1 transaction due to it is using propagation value REQUIRED_NEW. So, it creates a new transaction for method2.

MANDATORY:

This propagation value says that existing opened transactions must be there otherwise the container will throw an exception.

Syntax: @Transactional (propagation=Propagation. MANDATORY)

NEVER:

This propagation value says that throw an exception if the active transaction is present.

Syntax: @Transactional (propagation=Propagation. NEVER)

NOT_SUPPORTED:

This propagation value says that if any active transaction is there, pause that transaction and execute business logic without the transaction.

Syntax: @Transactional (propagation=Propagation. NOT_SUPPORTED)

NESTED:

This propagation value says that if the current transaction exists, executes within nested transaction otherwise it will behave like REQUIRED.

Syntax: @Transactional (propagation=Propagation. NESTED)

SUPPORTS:

This propagation value says that execute within a transaction if it is available otherwise execute without the transaction.

Syntax: @Transactional (propagation=Propagation. SUPPORTS)

6. @Transactional is on Service or DAO layer?

The service layer holds business logic. It is recommended to use @Transactional on the service layer rather than the DAO layer. If your application has only CRUD operations, then you can use it at the DAO layer.

The reason to  define transaction boundaries at the service layer is

Suppose one method is there where we are calling 3 different Dao layer operations in a method. If the first Dao operation failed and the other two Dao operations still passed. Then we will end up with an inconsistency database state. Annotating the service layer will help us to avoid these problems.

7.Spring Declarative Transaction management Conclusion

We have beautifully presented Spring Framework declarative transaction management concept with its configuration and @Transactional annotation along with its attributes.

Hope you like it. if you want more information, go through the following link

Link:

https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-programmatic

8. References

1.spring-framework-transaction

2.https://en.wikipedia.org/wiki/Isolation_(database_systems)

3. spring-boot

4. spring-mvc

Was this post helpful?

Leave a Reply

Your email address will not be published. Required fields are marked *