A detailed explanation of Spring transaction mechanism

Source: Internet
Author: User
Tags savepoint

Original source: Taubonren

The spring transaction mechanism mainly includes declarative transactions and programmatic transactions, where declarative transactions are emphasized, and programmatic transactions are not widely used in real-world development, and are for reference only.

Spring declarative transactions let us get away from complex transaction processing. So that we no longer have to deal with these operations such as getting connections, closing connections, committing transactions, and rolling back. There is no need for us to deal with a lot of try...catch...finally code in transaction-related methods. A very important concept when we use Spring declarative transactions is transaction properties. Transaction properties are typically composed of the propagation behavior of the transaction, the isolation level of the transaction, the timeout value of the transaction, and the transaction read-only flag. When we are doing a transaction partition, we need to define the transaction, that is, to configure the properties of the transaction.

The following is a detailed explanation of the four properties of the transaction, only for your study reference:

Spring defines these properties in the Transactiondefinition interface for Platfromtransactionmanager use. Platfromtransactionmanager is the core interface of spring transaction management.

123456 < Code class= "Java keyword" >public interface transactiondefinition { int Getpropagationbehavior (); //returns the propagation behavior of the transaction. int getisolationlevel (); //returns the isolation level of a transaction, which is used by the transaction manager to control which data within this transaction can be seen by another transaction. int gettimeout (); //returns how many seconds a transaction must complete. boolean isreadonly (); //whether the transaction is read-only, the transaction manager is able to optimize based on this return value to ensure that the transaction is read-only. }

1. Define five isolation levels in the Transactiondefinition interface:

Isolation_default This is a platfromtransactionmanager default isolation level, using the database default transaction isolation level. The other four correspond to the isolation level of JDBC;

Isolation_read_uncommitted This is the lowest isolation level for transactions, and it allows a transaction to see uncommitted data for this transaction. This isolation level produces dirty reads, non-repeatable reads, and Phantom reads.

Isolation_read_committed guarantees that a transaction modified data is committed before it can be read by another transaction. Another transaction cannot read uncommitted data for the transaction. This level of transaction isolation avoids dirty reads, but non-repeatable reads and phantom reads can occur.

Isolation_repeatable_read This transaction isolation level prevents dirty reads and cannot be read repeatedly. However, Phantom reads may occur. In addition to ensuring that one transaction cannot read uncommitted data from another transaction, it ensures that the following conditions are avoided (non-repeatable read).

Isolation_serializable This is the most cost-effective, but most reliable, transaction isolation level. Transactions are processed for sequential execution. In addition to preventing dirty reading, non-repeatable reading, but also avoids phantom reading.

1:dirty reads (dirty read). In other words, the uncommitted (and still cached) data for transaction A is read by transaction B, and if transaction a fails to roll back, the data read by transaction B is wrong.
2:non-repeatable reads (data cannot be read repeatedly). For example, the value of reading data-total-two places in transaction a. At the first reading, total is 100, then transaction b changes the total data to 200, and transaction a reads again, and the result is that total turns out to be 200, causing transaction a data chaos.
3:phantom reads (phantom read data), which is similar to non-repeatable reads, is also an issue that is inconsistent with multiple reads in the same transaction. But non-repeatable reads is inconsistent because the data set he wants to take is changed (such as total data), but the inconsistency of the data that Phantom reads to read is not a change in the data set that he wants to read, but a change in his conditional data set. For example, select Account.id where account.name= "ppgogo*", the first time to read 6 eligible IDs, the second time, because transaction B to the name of an account from "DD" to "Ppgogo1″, As a result, 7 data were taken out.

2. Seven transactional propagation behaviors are defined in the Transactiondefinition interface:

(1) propagation_required If there is a transaction, the current transaction is supported. If there is no transaction, a new transaction is opened.

Java code:

1234567891011 //事务属性 PROPAGATION_REQUIRED methodA{ …… methodB(); …… }//事务属性 PROPAGATION_REQUIRED methodB{    …… }

With spring declarative transactions, Spring uses AOP to support declarative transactions, automatically deciding whether to open a transaction before a method call, based on the transaction properties, and then deciding the transaction to commit or roll back after the method executes.

Call the MethodB method separately:

Java code

12345 main{ metodB(); }


Java code

12345678910111213141516171819202122232425262728293031323334353637 Main{ Connection con=null; try{ con = getConnection(); con.setAutoCommit(false); //方法调用methodB(); //提交事务con.commit(); } Catch(RuntimeException ex){             //回滚事务con.rollback();   } finally{ //释放资源closeCon(); } }

Spring guarantees that all calls in the MethodB method get to the same connection. When calling MethodB, there is a transaction that does not exist, so a new connection is obtained and a new transaction is opened.

When MethodA is called separately, MethodB is called within MethodA.

The execution effect is equivalent to:

Java code

123456789101112131415161718192021222324252627          main{ Connection con = null; try{ con = getConnection();     methodA(); con.commit(); } catch(RuntimeException ex){ con.rollback(); } finally{    closeCon(); }

When calling MethodA, there is no transaction in the environment, so a new transaction is opened. When MethodB is called in MethodA, there is already a transaction in the environment, so MethodB joins the current transaction.

(2) Propagation_supports If there is a transaction, the current transaction is supported. If there is no transaction, the execution is non-transactional. However, for transaction managers with transactional synchronization, Propagation_supports is slightly different from not using transactions.

Java code:

123456789 //事务属性 PROPAGATION_REQUIRED methodA(){   methodB(); }//事务属性 PROPAGATION_SUPPORTS methodB(){   …… }

When invoking MethodB purely, the MethodB method is non-transactional execution. When Methda is called, MethodB is added to the MethodA transaction and executed in the transaction.

(3) Propagation_mandatory if a transaction already exists, the current transaction is supported. Throws an exception if there is no active transaction.

Java code:

123456789 //transaction properties propagation_required       methoda () { &NBSP;&NBSP; methodb ();                          //transaction properties propagation_mandatory      methodb () {       &NBSP;&NBSP;&NBSP;&NBSP;

When MethodB is called separately because there is currently no active transaction, an exception throws the new Illegaltransactionstateexception ("Transaction propagation ' mandatory ' But no existing transaction found "); when MethodA is called, MethodB is added to the transaction of MethodA and executed by the transaction.

(4) Propagation_requires_new always opens a new transaction. If a transaction already exists, the existing transaction is suspended.

Java code:

1234567891011 //事务属性 PROPAGATION_REQUIRED methodA(){    doSomeThingA(); methodB(); doSomeThingB(); }//事务属性 PROPAGATION_REQUIRES_NEW methodB(){    …… }

Java code:

123 main(){   methodA(); }


Java code:

123456789101112131415161718192021222324252627282930313233 main(){   TransactionManager tm = null; try{   //获得一个JTA事务管理器     tm = getTransactionManager();     tm.begin();//开启一个新的事务     Transaction ts1 = tm.getTransaction();     doSomeThing();     tm.suspend();//挂起当前事务     try{       tm.begin();//重新开启第二个事务       Transaction ts2 = tm.getTransaction();       methodB();       ts2.commit();//提交第二个事务    }   Catch(RunTimeException ex){       ts2.rollback();//回滚第二个事务   }   finally{      //释放资源    }     //methodB执行完后,复恢第一个事务     tm.resume(ts1); doSomeThingB();     ts1.commit();//提交第一个事务 } catch(RunTimeException ex){    ts1.rollback();//回滚第一个事务 } finally{    //释放资源 } }

Here, I call ts1 the outer transaction, TS2 called the inner transaction. As can be seen from the above code, TS2 and Ts1 are two separate transactions that are irrelevant to each other. The success of TS2 is not dependent on ts1. If the MethodA method fails with the DOSOMETHINGB method after calling the MethodB method, the result of the MethodB method is still committed. The results of the code other than MethodB are rolled back. With propagation_requires_new, you need to use Jtatransactionmanager as the transaction manager.
(5) propagation_not_supported is always executed in a non-transactional manner and suspends any existing transactions. With propagation_not_supported, you also need to use Jtatransactionmanager as the transaction manager. (code example above, can be introduced similarly)

(6) Propagation_never is always performed in a non-transactional manner and throws an exception if there is an active transaction;

(7) propagation_nested If an active transaction exists, it is run in a nested transaction. If there is no active transaction, it is performed by the Transactiondefinition.propagation_required property. This is a nested transaction that only supports Datasourcetransactionmanager as the transaction manager when using the JDBC 3.0 driver. A JDBC-driven Java.sql.Savepoint class is required. There are some JTA transaction manager implementations that may also provide the same functionality. With propagation_nested, you also need to set Platformtransactionmanager's Nestedtransactionallowed property to true; The Nestedtransactionallowed property value defaults to false;

Java code:

1234567891011 //事务属性 PROPAGATION_REQUIRED methodA(){    doSomeThingA();    methodB();    doSomeThingB(); }//事务属性 PROPAGATION_NESTED methodB(){   …… }

If the MethodB method is called separately, it is performed by the required property. If you call the MethodA method, it is equivalent to the following effect:

Java code:

123456789101112131415161718192021222324252627 main(){ Connection con = null; Savepoint savepoint = null; try{    con = getConnection();    con.setAutoCommit(false);    doSomeThingA();    savepoint = con2.setSavepoint();    try{        methodB();    }catch(RuntimeException ex){       con.rollback(savepoint);    }    finally{      //释放资源   }   doSomeThingB();    con.commit(); } catch(RuntimeException ex){   con.rollback(); } finally{    //释放资源 } }

When the MethodB method is called, the Setsavepoint method is called, saving the current state to savepoint. If the MethodB method call fails, it reverts to the previously saved state. It is important to note, however, that the transaction is not committed at this time, and if the subsequent code (DOSOMETHINGB () method) call fails, the rollback includes all operations of the MethodB method.

Nested transactions A very important concept is that the inner transaction relies on the outer layer. When the outer transaction fails, the actions of the inner layer are rolled back. The failure of the inner transaction operation does not cause the rollback of the outer transaction.

The difference between propagation_nested and propagation_requires_new: They are very similar, like a nested transaction, and if there is no active transaction, a new transaction will be opened. With Propagation_requires_new, the inner transaction and the outer transaction are like two separate transactions, and once the inner transaction commits, the outer transaction cannot roll it back. Two transactions do not affect each other. Two transactions are not a true nested transaction. It also requires the support of the JTA transaction manager.

When using propagation_nested, the rollback of the outer transaction can cause a rollback of the inner transaction. The exception of the inner transaction does not cause the rollback of the outer transaction, which is a true nested transaction. Datasourcetransactionmanager with savepoint support for propagation_nested, JDBC 3.0 or more drivers and more than 1.4 JDK version support are required. Other JTA Trasactionmanager implementations may have different support options.

Propagation_requires_new starts a new, "internal" transaction that does not depend on the environment. This transaction will be fully commited or rolled back without relying on external transactions, it has its own isolation range, its own locks, and so on. When an internal transaction starts executing, the external transaction will be suspended and the external transaction will continue to execute at the end of the housekeeping transaction.

On the other hand, propagation_nested begins a "nested" transaction, which is a real child of a transaction that already exists. When the dive set starts executing, it will get a savepoint. If this nested transaction fails, we will roll back to this savepoint. A latent transaction is a part of an external transaction that is committed only after the external transaction has ended.

Thus, the biggest difference between propagation_requires_new and propagation_nested is that propagation_requires_new is entirely a new business, and propagation_nested is a child of an external transaction, and if an external transaction commits, a nested transaction is also commit, and the same rule applies to roll back.
Propagation_required should be our first transaction propagation behavior. It can satisfy most of our business needs.

A detailed explanation of Spring transaction mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.