In this article I’ll discuss the use of the Spring Framework Transactions, to make the application more secure and without inconsistencies. But before you initiate a transaction in Spring, let’s first understand what are transactions. The transaction concept can be described with the acronym ACID. 1. Atomicity:- A transaction must be treated as a single operation, this means that all commands in this transaction can be completed successfully or unsuccessfully. Nothing will be saved if at least one command 100 goes wrong, everyone should run successfully without errors. 2. Consistency: This is the consistency of integrity of the database, they are: unique and primary keys etc. 3. Isolation: Many transaction can be executed at the same time, the insulation ensures that each transaction is isolated from the other, thereby preventing data corruption. 4. Durability: A transaction should continue after being persisted and can not be deleted by system failures.
Transactions with Spring Framework
Once you understand the concept, we should also keep in mind that there are two ways to work with transactions in an application: Programmatically or Declaratively. Working Programmatically brings immense flexibility to manage their transactions, but the maintainability of the code becomes difficult and costly. On the other hand, working Decoratively is more stylish and follows good programming practices, since you’ll be separating completely the control of transaction of business rules. When it comes to Spring Framework you can work decoratively via XML or annotations, but in this article we will focus on the notes.
Before you start using the transactions you need to tell Spring that you want to perform a transaction control via annotations, this is done through configuration shown in Listing 1 in the file applicationContext.xml.
Listing 1 : Enabling transactions via annotations in applicationContext.xml
<tx:annotation-driven transaction-manager="transactionManager"/>
After this you will be able to use annotation @Transactional in order to define a particular method that should be within a transaction.
Isolation
The first parameter is Isolation, this can be defined as follows:
Listing 2 : Isolation Level
@ Transactional (isolation = Isolation.READ_COMMITTED)
The possible types of isolation are:
- ISOLATION_DEFAULT: Isolation level standard.
- ISOLATION_READ_COMMITTED: Prevents just “dirty reads”.
- ISOLATION_READ_UNCOMMITED: Indicates “dirty reads”, “non-repeatable reads” and “Phatom reads” may occur, or will not be prevented.
- ISOLATION_REPEATABLE_READ: Prevents just “dirty reads” and “non-repeatable reads.”
- ISOLATION_SERIALIZABLE: Prevents “dirty reads”, “non-repeatable reads” and “Phatom reads.”
My focus is not to teach the background operation of transaction, but only how its applied to Spring. I will briefly explain types of readings prevented in Isolation.
- Dirty Read : This occurs when a transaction writes an X value and a transaction value B read this without having done the transaction commit or rollback the transaction. The case of a transaction rollback, the value of the transaction B read becomes invalid.
- Non-repeatable read : Occurs when a single transaction in a line is read twice and the values of these two readings are different.
- Read Phatom : This occurs when two similar queries are executed and the result of the latter is different from the first.
Defining Propagation
Another very important parameter to be defined in a transaction in Spring is how transaction will be held. Here are the possible ways of propagation:
- PROPAGATION_MANDATORY: Forces the use of a transaction, if there is no current transaction, an exception is thrown.
- PROPAGATION_NESTED: Execute within a nested transaction if a current transaction exists.
- PROPAGATION_NEVER: Prevents the use of a transaction. If there is a current transaction, an exception is thrown.
- PROPAGATION_NOT_SUPPORTED: It uses the current transaction. This always runs with no transaction.
- PROPAGATION_REQUIRED: Uses the current transaction if exists does not exist creates a new transaction.
- PROPAGATION_REQUIRES_NEW: Creates a new transaction, if there is already a current stops this.
- PROPAGATION_SUPPORTS: Uses the current transaction if one exists, otherwise executes without transaction.
There is a parameter “readOnly” in the @Transactional annotation. This specifies that no operation can be performed like DML (Insert, Update or Delete), ie only queries can be performed.
In Listing 3 we have defined a class that uses Spring’s transaction control, this uses a readOnly = false and PROPAGATION_REQUIRED, so always ensure that the Save method will run within a transaction.
Listing 3 : Using @Transactional practice
@ Repository public class implements ProductDAOImpl ProductDAO { private SessionFactory sessionFactory; @ Autowired public ProductDAOImpl (SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } private Session currentSession () { sessionFactory.getCurrentSession return (); } @ Override @ Transactional (propagation = Propagation.REQUIRED, readOnly = false) public void save (ProductTech product) { currentSession (.) save (product); System.out.println ("product saved with sucess"); } }
The other annotations such as @Autowired and @Repository settings are also Spring annotations, which will not be focused in this article. As you can see in the “save” method we have defined the transaction as PROPAGATION_REQUIRED, therefore if we had 10 saves in the save, everyone should be required to succeed in their implementation, otherwise a rollback would be done.
Summary
Reference:
- Managing transactions in EJB 3.0
- Spring Auto scanning components
- Introduction to Java Persistence API(JPA)
This article aims at practical use and fast Transaction, once you finish this reading you are able to use this feature of Spring. If you are interested in receiving the future articles, please subscribe here. follow us on @twitter and @facebook.