Analysis of the propagation characteristics of spring transaction--The confusion of nested invocation of transaction method

Source: Internet
Author: User

Review of the spring transaction propagation mechanism


Spring transaction One is misinformation very broadly: one transaction method should not invoke another transaction method, otherwise two transactions will be generated. As a result, developers shackled in the design of transaction methods, fearing that they would step on a mine accidentally.
In fact, this is a misunderstanding caused by the spring transaction propagation mechanism, spring's support for transaction control is described in the Transactiondefinition class, which has several important interface methods:

    • int Getpropagationbehavior (): The propagation behavior of a transaction
    • int Getisolationlevel (): The isolation level of the transaction
    • int GetTimeout (): The expiration time of the transaction
    • Boolean isreadonly (): Transactional read-write characteristics



Obviously, in addition to the propagation behavior of the transaction, other features of the transaction spring is done with the functionality of the underlying resources, and spring is nothing more than a proxy role. But the spread of the transaction is spring's ability to provide the developer with its own framework, the most precious gift that spring offers to developers, and misinformation's claim to tarnish the most beautiful aura of the spring transaction framework.

The so-called transaction propagation behavior is how transactions are propagated between these methods when multiple transactional methods are called each other. Spring supports the following 7 types of transactional propagation behavior.

    • Propagation_required: If there is no current transaction, create a new transaction, and if one already exists, add it to the transaction . This is the most common choice.
    • Propagation_supports: Supports the current transaction and is executed in a non-transactional manner if no transaction is currently in use.
    • Propagation_mandatory: Uses the current transaction and throws an exception if there is no current transaction.
    • Propagation_requires_new: Creates a new transaction and suspends the current transaction if a transaction is currently present.
    • Propagation_not_supported: Executes the operation in a non-transactional manner, suspending the current transaction if a transaction is currently present.
    • Propagation_never: Executes in a non-transactional manner and throws an exception if a transaction is currently present.
    • Propagation_nested: Executes within a nested transaction if a transaction is currently present. If there is currently no transaction, perform a similar operation as propagation_required.



Spring's default transactional propagation behavior is propagation_required, which is suitable for most situations where multiple servivex#methodx () are working in a transactional environment (that is, both are enhanced by spring transactions). And the following call chain exists in the program: Service1#method1 ()->service2#method2 ()->service3#method3 (), Then the 3 methods of these 3 service classes work in the same transaction through spring's transaction propagation mechanism.

Mutually nested service methods

Let's take a look at the example, the Userservice#logon () method internally calls the Userservice#updatelastlogon time () and the Scoreservice#addscore () method, These two classes are inherited from Baseservice. The class structure between them is as follows:

The Userservice#logon () method internally invokes the Scoreservice#addscore () method, each of which has transaction enhancements through Spring AOP, which works in the same transaction. To see the specific code:

 PackageCom.baobaotao.nestcall; @Service ("UserService") Public classUserServiceextendsBaseservice {@AutowiredPrivateJdbcTemplate JdbcTemplate; @AutowiredPrivateScoreservice Scoreservice; //① This method nested calls to other methods of this class and methods of other service classes     Public voidlogon (String userName) {System.out.println ("Before Userservice.updatelastlogontime ..."); Updatelastlogontime (userName);//①-1 Other methods of this service classSystem.out.println ("After userservice.updatelastlogontime ..."); System.out.println ("Before Scoreservice.addscore ..."); Scoreservice.addscore (UserName,20);//other ways to ①-2 other service classesSystem.out.println ("After Scoreservice.addscore ..."); }     Public voidupdatelastlogontime (String userName) {String sql= "UPDATE t_user u SET u.last_logon_time =?" WHERE user_name =? ";    Jdbctemplate.update (SQL, System.currenttimemillis (), userName); }

The Scoreservice bean is injected into the userservice, and the code for Scoreservice is as follows:

 package   Com.baobaotao.nestcall; ... @Service (  "Scoreuserservice"  public  class  scoreservice extends   baseservice{@Autowired  private   JdbcTemplate JdbcTemplate;  public  void  addscore (String  UserName, int   toadd) {String sql  = "UPDATE T_user u SET u.score = U.score +? WHERE user_name =? "        ;    Jdbctemplate.update (SQL, Toadd, userName); }}

Add Spring AOP Transaction enhancements to all public methods in Scoreservice and UserService through spring configuration, letting UserService logon () and Updatelastlogontime () and Scoreservice Addscore () methods work in a transactional environment. The following are the key configuration codes:

<?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns= "Http://www.springframework.org/schema/beans"Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"Xmlns:context= "Http://www.springframework.org/schema/context"xmlns:p= "http://www.springframework.org/schema/p" xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP"Xmlns:tx= "Http://www.springframework.org/schema/tx"xsi:schemalocation= "Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http//Www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd 
HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
Http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"><context:component-scan base- Package= "Com.baobaotao.nestcall"/>... ..<bean id= "Jdbcmanager"class= "Org.springframework.jdbc.datasource.DataSourceTransactionManager"P:datasource-ref= "DataSource"/> <!--① All public methods with the following configuration for all of the subclasses of the inherited Baseservice class are added transaction enhancement--<aop:config proxy-target-class= "true" > <aop:pointcut id= "Servicejdbcmethod"expression= "Within (com.baobaotao.nestcall.baseservice+)"/> <aop:advisor pointcut-ref= "Servicejdbcmethod" advice-ref= " Jdbcadvice "order=" 0 "/> </aop:config> <tx:advice id=" Jdbcadvice "transaction-manager=" Jdbcmanager "> <tx:attributes> <tx:method name= "*"/> </tx:attributes> </tx:advice>< /beans>

Set the log level to debug, start the Spring container and execute the Userservice#logon () method, and carefully observe the output log as follows:

before Userservice.logon method ...//① creates a transactionCreatingNewtransaction with Name [Com.baobaotao.nestcall.UserService.logon]: Propagation_required,isolation_default Acquired Connection [Jdbc:mysql://localhost:3306/sampledb, [email protected], mysql-ab JDBC Driver] for JDBC transactionSwitching JDBC Connection [jdbc:mysql://localhost:3306/sampledb, [email protected], Mysql-ab JDBC Driver] to manual commitbefore Userservice.updatelastlogontime ...<!--②updatelastlogontime () and logon () in the same bean do not take an action that joins an already existing transaction context, but instead "naturally" work in the same transaction contexts-executing prepared SQL update executing prepared SQL statement [Update t_user u SET u.last_logon_time= ? WHERE user_name =?] SQL Update affected1rows after userservice.updatelastlogontime ... before Scoreservice.addscore ...//The ③scoreservice#addscore method is added to the transaction context started at ①participating in existing transaction executing prepared SQL update executing prepared SQL statement [Update t_user U SET U.score= U.score +? WHERE user_name =?] SQL Update affected1rows after Scoreservice.addscore ... Initiating transaction commit committing JDBC transaction on Connection [Jdbc:mysql://localhost:3306/sampledb, [email protected], Mysql-ab JDBC Driver]... after Userservice.logon method ...

From the output log above, it is clear that spring has started a new transaction for the Userservice#logon () method, while Userserive#updatelastlogontime () and Userservice#logon () are in the same class , the occurrence of transactional propagation behavior is not observed, and its code blocks appear to be "merged directly" into Userservice#logon ().

However, when executing to the Scoreservice#addscore () method, we observe the behavior of a transaction propagating: " participating in existing transaction ",
This means that scoreservice#addscore () is added to the transaction context of Userservice#logon (), and both share the same transaction .
So the end result is that UserService's logon (), Updatelastlogontime (), and Scoreservice Addscore all work in the same transaction.

Note: The above content is from "Spring 3.x enterprise application development actual combat"

http://blog.csdn.net/hy6688_/article/details/44763869

Analysis of the propagation characteristics of spring transaction--The confusion of nested invocation of transaction method

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.