Spring transaction Propagation and Its Implementation Principles, springpropagation

Source: Internet
Author: User
Tags savepoint

Spring transaction Propagation and Its Implementation Principles, springpropagation

This article focuses on spring transaction Propagation and Its Implementation Principles. The specific introduction is as follows.

Introduction

Spring is now a de facto standard for java development, thanks to its convenience, complete functionality, and ease of use. During the development process, operations on the database are very common, and transactions are involved when DB is involved. During the normal development process of transactions, even if the program is not noticed, normal execution of the program will not have any side effects, but if an exception occurs and the transaction is not well handled, unexpected results may occur. Spring encapsulates various transactions, especially declarative transactions, to make development more comfortable. Spring expands transactions and supports defining multiple propagation attributes, which is also the focus of this article.

What is a transaction?

Strictly speaking, a transaction is short for multiple operations. These operations either take effect or none take effect (equivalent to not executed). A general operation process is simplified as follows:

Try {Connection conn = getConnection (); // execute some database operations} catch (Exception e) {conn. rollback () ;}finally {conn. close ();}

The above code shows some problems:

  • Too many useless fixed code
  • If a request needs to call multiple service interfaces, it is difficult to control transactions more precisely.
  • It is difficult to unify the encoding method across multiple underlying data layers, such as jdbc, mybatis, hibernate, and jta.

Spring provides declarative transactions, so that we do not need to focus on the specific implementation of the underlying layer, shielding a variety of different underlying implementation details, in order to support a variety of complex businesses to precisely control transactions, spring provides the propagation attribute of transactions, and combines declarative transactions to achieve a major transaction weapon.

Spring transaction propagation attribute Example Analysis

In the TransactionDefinition class, spring provides six propagation attributes, which are described in simple examples.

Warm Reminder: the addition of the current transaction mentioned below refers to the use of the same Connection at the underlying layer, but the transaction state object can be re-created without affecting. As mentioned in this article, only one transaction exists, indicating a Connection that shares the underlying layer, and does not care how many transaction status objects are created (TransactionStatus ).

1. PROPAGATION_REQUIRED

Note: If a transaction already exists, join the transaction. If no transaction exists, create a transaction. This is the default propagation property value.

Let's look at a small example. The Code is as follows:

@Transactionalpublic void service(){ serviceA(); serviceB();}@TransactionalserviceA();@TransactionalserviceB();

Both serviceA and serviceB declare transactions. By default, propagation = PROPAGATION_REQUIRED exists only one shared transaction during service calling. When any exception occurs, all operations are rolled back.

2. PROPAGATION_SUPPORTS

Note: If a transaction already exists, add it to the transaction. Otherwise, create a so-called null transaction (which can be considered as being executed without a transaction ).

Let's look at a small example. The Code is as follows:

public void service(){  serviceA();  throw new RunTimeException();}@Transactional(propagation=Propagation.SUPPORTS)serviceA();

There is no transaction currently during serviceA's execution, so the exceptions thrown in the service will not cause serviceA to roll back.

Let's look at a small example. The Code is as follows:

public void service(){  serviceA();}@Transactional(propagation=Propagation.SUPPORTS)serviceA(){ do sql 1 1/0; do sql 2}

Because serviceA does not have a transaction at runtime, if the underlying data source defaultAutoCommit = true, sql1 takes effect. If defaultAutoCommit = false, sql1 is invalid. If the service has the @ Transactional tag, serviceA shares service transactions (no longer dependent on defaultAutoCommit). At this time, serviceA is rolled back.

3. PROPAGATION_MANDATORY

Note: A transaction must exist currently; otherwise, an exception is thrown.

Let's look at a small example. The Code is as follows:

public void service(){  serviceB();  serviceA();}serviceB(){ do sql}@Transactional(propagation=Propagation.MANDATORY)serviceA(){ do sql }

In this case, the service Execution throws an exception. If defaultAutoCommit = true, serviceB will not roll back. If defaultAutoCommit = false, the serviceB execution is invalid.

4. PROPAGATN_REQUIRES_NEW

Note: If a transaction exists, encapsulate the content of the current transaction to an entity, create a new transaction, and accept this entity as a parameter for transaction recovery. A more straightforward statement is to pause the current transaction (no transaction is required currently) and create a new transaction. In this case, there is no dependency between the two transactions and new transactions can be rolled back, but external transactions continue to be executed.

Let's look at a small example. The Code is as follows:

@Transactionalpublic void service(){ serviceB(); try{  serviceA(); }catch(Exception e){ }}serviceB(){ do sql}@Transactional(propagation=Propagation.REQUIRES_NEW)serviceA(){ do sql 1 1/0;  do sql 2}

When calling the service interface, serviceA creates a new transaction because it uses REQUIRES_NEW. However, serviceA rolls back the entire service because of a running exception thrown by serviceA, however, an exception is caught in the service method, so serviceB is submitted normally. Note: try... The catch code is required. Otherwise, the service throws an exception, causing serviceB to be rolled back.

5. Propagation. NOT_SUPPORTED

Note: If a transaction exists, the current transaction is suspended, and the new method is executed in the environment where no transaction exists. in the environment where no spring transaction exists, SQL commit relies entirely on the defaultAutoCommit attribute value.

Let's look at a small example. The Code is as follows:

@Transactionalpublic void service(){  serviceB();  serviceA();}serviceB(){ do sql}@Transactional(propagation=Propagation.NOT_SUPPORTED)serviceA(){ do sql 1 1/0; do sql 2}

When calling the service method and executing code 1/0 in the serviceA method, an exception is thrown. Because serviceA is in a non-transactional environment, whether sql1 takes effect depends on the value of defaultAutoCommit, when defaultAutoCommit = true, sql1 takes effect, but the service throws an exception, so serviceB will be rolled back.

6. PROPAGATION_NEVER

Note: If a transaction exists, an exception is thrown; otherwise, the code is executed in the non-transaction environment.

Let's look at a small example. The Code is as follows:

public void service(){ serviceB(); serviceA();}serviceB(){ do sql}@Transactional(propagation=Propagation.NEVER)serviceA(){ do sql 1 1/0; do sql 2}

After the preceding example calls the service, if defaultAutoCommit = true, the serviceB method and sql1 in serviceA will take effect.

7. PROPAGATION_NESTED

Note: If a transaction exists, the SavePoint technology is used to save the current transaction status, and the underlying layer shares a connection. When an internal error occurs in NESTED, The SavePoint state is rolled back on its own, as long as an exception is caught, external transaction commit can be continued without being disturbed by the embedded business. However, if an exception is thrown by an external transaction, the entire large transaction will be rolled back.

Note: The spring configuration Transaction Manager must specify nestedTransactionAllowed = true as follows:

 <bean id="dataTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataDataSource" />  <property name="nestedTransactionAllowed" value="true" /> </bean>

Let's look at a small example. The Code is as follows:

@Transactionalpublic void service(){ serviceA(); try{  serviceB(); }catch(Exception e){ }}serviceA(){ do sql}@Transactional(propagation=Propagation.NESTED)serviceB(){ do sql1 1/0; do sql2}

ServiceB is an embedded service that throws an internal runtime exception. Therefore, serviceB is rolled back. As the service captures an exception, serviceA can submit the service normally.

Let's take an example. The Code is as follows:

@Transactionalpublic void service(){  serviceA();  serviceB();  1/0;}@Transactional(propagation=Propagation.NESTED)serviceA(){ do sql}serviceB(){ do sql}

The entire service method is rolled back because an exception is thrown by the service. (This is different from PROPAGATION_REQUIRES_NEW. The embedded business in the NESTED mode will be rolled back due to exceptions in external transactions .)

Implementation Analysis

The preceding example illustrates several propagation Attributes provided by spring transactions to meet different business needs. Next, let's take a look at what is the most important technical dependency of spring to implement these propagation attributes. This section briefly describes PROPAGATION_REQUIRES_NEW and Propagation. NESTED.

1. PROPAGATION_REQUIRES_NEW implementation principle

Call the following code:

@Transactionalpublic void service(){ serviceB(); try{  serviceA(); }catch(Exception e){ }}@Transactional(propagation=Propagation.REQUIRES_NEW)serviceA(){ do sql 1 1/0; do sql 2}serviceB(){ do sql}

The execution principle is as follows:

A. Create a transaction status object, obtain a new connection, and reset the attributes of the connection, such as autoCommit, fetchSize, and timeout.

B. Bind the connection to the ThreadLocal variable.

C. Suspend the current transaction and encapsulate the current transaction status object, connection, and other information into a SuspendedResources object for restoration.

D. create a new transaction status object, obtain a new connection, reset the autoCommit, fetchSize, timeout, and other attributes of the new connection, and save the SuspendedResources object for transaction recovery, bind a new connection to the ThreadLocal variable (overwrite Operation)

E. catch exceptions, roll back connections in ThreadLocal, restore connection parameters, close connections, and recover SuspendedResources

F. Submit the connection in the ThreadLocal variable (resulting in serviceB being submitted), restore the connection parameters, close the connection, and return the connection to the data source.

So the execution result of the program is serviceA rolled back and serviceB submitted successfully.

2. PROPAGATION_NESTED implementation principle

Call the following code:

@Transactionalpublic void service(){ serviceA(); try{   serviceB(); }catch(Exception e){ }}serviceA(){ do sql}@Transactional(propagation=Propagation.NESTED)serviceB(){ do sql1 1/0; do sql2}

The execution principle is as follows:

A. Create a transaction status object, obtain a new connection, and reset the attributes of the connection, such as autoCommit, fetchSize, and timeout.

B. Bind the connection to the ThreadLocal variable.

C. Mark the current transaction status object, obtain the ThreadLocal connection object, and save the SavePoint of the current connection for exception recovery. The SavePoint is the status after serviceA is executed.

D. When an exception is caught, use the SavePoint in c to roll back the transaction, that is, to roll back the state to the status after serviceA is executed. All executions of the serviceB method do not take effect.

E. Obtain the connection object in ThreadLocal, submit the transaction, restore the connection property, and close the connection.

Others

Based on the underlying data source, spring uses technical points such as ThreadLocal and SavePoint to implement multiple transaction propagation attributes, facilitating various complex businesses. Only by understanding the principles of propagation attributes can we better control spring transactions. Spring rollback transactions rely on exception capture. By default, transactions are rolled back only when RuntimeException and Error are thrown. Of course, you can configure them, for more information, see @ Transactional.

Summary

Spring declarative transactions bring us great convenience. to make good use of this tool and understand the underlying principles, it is necessary. This article is just the tip of the iceberg of spring transactions, on this basis, you can explore it in depth.

The above is the full description of spring transaction Propagation and its implementation principles, and I hope to help you. If you are interested, you can continue to refer to other related topics on this site. If you have any shortcomings, please leave a message. Thank you for your support!

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.