The concept of transaction is essential to any business application. A transaction, in layman’s term, makes sure that only contracted-upon, dependable, and satisfactory state changes are made to a system, regardless of any failure in the system or issues arising due to concurrent access to the system’s resources.
The present application architectures brings along with it lot of complexities, having veracious systems joined together achieving a business case into reality. This brings along challenges to existing transaction models, which application frameworks keep on innovating to achieve it. Spring provides excellent transaction management capabilities considering modern day application’s transaction requirement and complexities.
The initial sections of this chapter deal with fundamental concepts in and around transactions in general. Later sections concentrate on how Spring comes into picture to address these transaction concepts.
In simple terms transaction can be thought of as an interaction with a system resulting in a state change of the system. It is a common practice to mention transaction as a “unit of work”. In most of the cases, these interactions can be successful, but any number of unforeseen events can interrupt this interaction, leaving the system in an incomplete, inconsistent and unstable form which is not good for the overall application system.
By putting the interaction with the system inside a transaction boundary, you get a guarantee that the interaction is achieved successfully, and in case if it is not, it keeps the system in consistent and stable form.
In simpler terms, in reality, any application is bound to fail at some point in its life. This might result from programming problems, loss of power supply, hardware issues, incorrect input data, user error and so forth. The causes are many, but the end result is same; you application in an inconsistent manner. Putting your interaction with the application inside a transaction boundary can mitigate it to some extend and this is the reason you should use transaction in your application.
In any modern day applications, transactions are required to satisfy the so called ACID properties, that is, the set of operations involved in a transaction should occur atomically, should be consistent, should be isolated from other operations, and their effects should be durable in time. We will explain each of the following properties:
It is the property of a transaction to either complete successfully or not at all in the event of complete or partial failure. All the activities within a particular transaction should be indivisible, that is, atomic in nature.
It is the property of a transaction to begin and end in a state which is consistent and not breaking any integrity constraints. A database or other persistent store defines referential and entity integrity rules to ensure that data in the store is consistent at all times. A transaction that changes the data must ensure that the data remains in a consistent state and that data integrity rules are not violated, regardless of whether the transaction is a success or failure. The data in the store may not be consistent during the duration of the transaction, but the inconsistency is invisible to other transactions, and consistency must be restored when the transaction completes.
It is the property of a transaction to perform operations isolated from all other operations in a particular application. One transaction should not see other transaction’s data in an intermediate state at any stage. When multiple transactions are in progress, one transaction may want to read the same data another transaction has changed but not committed. Up until the transaction commits, the changes made by it should be treated as transient state, because the transaction could roll back the change. If other transactions read intermediate or transient states caused by a transaction in progress, additional application logic must be executed to handle the effects of some transactions having read potentially erroneous data. This property tells how concurrent transaction should behave in which it actions on same set of data in an application.
There are various isolation levels which exist in the case of transaction, which will be covered in later sections of this chapter.
It is the property of a transaction wherein, state changes made within a transactional boundary in an application must be persisted onto permanent storage media, such as disks, databases, or file systems. If due to any reason application fails after the transaction has committed, the system should guarantee that the effects of the transaction will be visible to the application when it restarts. Any change committed by one transaction must be durable until another valid transaction changes the data.
There are various means by which a transaction is classified into different types. Some of the well-known transaction type terminology is explained below so that you have a clear idea when these are used at various stages of this chapter.
Transactions that deal with just one resource such as one database are known as local transactions. Coding using local transactions can be easier but has significant disadvantages attached to it. They are:
- It cannot work with multiple transactional resources.
- Invasive/disturbing to the underlying programming model.
Transactions that span multiple resources such as more than one database or a database and a messaging engine are called global transactions. They too have advantages attached to it, which can be summarized as below:
- The application server manages global transactions using JTA (Java Transaction API), which can be cumbersome API to use.
- Usually, JTA in an application server is sourced from JNDI, which indirectly brings in dependency of JNDI to your application.
Spring addresses disadvantage of both local and global transactions alike, by addressing these disadvantages, as well as introducing its own unique advantages which are covered in the section named “Advantages of Spring Transaction Management” below.
Note: For Java Standard Environment, stand-alone JTA implementations can be wired to use the Spring’s JtaTransactionManager, which is covered in the following sections of this chapter. This way Spring addresses both the disadvantages mentioned in the above section.
Page Visitors: 7730