Declarative transactions are divided into declarative and programmatic types: declarative transactions: Declarative transactions control and manage the various characteristics of a transaction through annotations. Coded (programmatic) transactions: This refers to the declaration of an encoded transaction.

11.1. Transaction implementation by encoding method:



11.2. Construction of declarative transaction environment

11.2.1. Prepare the test database

## create tx database drop database if exists' tx '; CREATE database `tx`; USE 'tx'; ## DROP TABLE IF EXISTS 'user'; CREATE TABLE 'user' (' id 'int primary key auto_increment,' username 'varchar(50) NOT NULL, `money` int(11) DEFAULT NULL ); Insert into 'user' (' username ', 'money') values (' 三',1000); ## drop table if exists' book '; Create table 'book' (' id 'int primary key auto_increment,' name 'varchar(500) not null,' stock 'int); Insert into book(' name ', 'stock') values(' Java ',100),('C++ ',100); Select * from book; select * from user;Copy the code

11.2.2 create a Java project and import the Jar package



Import jar package:

Com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar Commons logging - 1.1.3. Jar druid - 1.1.9. Jar Mysql connector - Java - 5.1.37 - bin. Jar spring aop -- 4.3.18. The jar spring - beans - 4.3.18. The jar Spring - the context - 4.3.18. RELEASE. Jar spring - core - 4.3.18. The jar spring - expression - 4.3.18. The jar Spring - JDBC - 4.3.18. RELEASE. Jar spring - the orm - 4.3.18. The jar spring - test - 4.3.18. The jar spring - tx - 4.3.18. The jarCopy the code

Configure the jdbc.properties property profile:

url=jdbc:mysql://localhost:3306/tx
user=root
password=root
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
Copy the code

Configure the Spring configuration file:

<? The 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd "> <! <context:component-scan base-package="com"></context:component-scan> <! -- load the JDBC. The properties attribute configuration file - > < context: the property - placeholder location = "classpath: JDBC. Properties" / > <! - configure the database connection pool - > < bean id = "dataSource" class = "com. Alibaba. Druid. Pool. DruidDataSource" > < property name = "username" value="${user}"/> <property name="password" value="${password}"/> <property name="url" value="${url}"/> <property name="driverClassName" value="${driverClassName}"/> <property name="initialSize" value="${initialSize}" /> <property name="maxActive" value="${maxActive}"/> </bean> <! - configured jdbcTemplate tools - > < bean id = "jdbcTemplate" class = "org. Springframework. JDBC. Core. JdbcTemplate" > < property name="dataSource" ref="dataSource" /> </bean> </beans>Copy the code

Experiment 1: Test the default transaction of Service layer

@Repository public class BookDao { @Autowired JdbcTemplate jdbcTemplate; Public void updateBook() {jdbctemplate.update ("update book set name = 'updateBook '"); } } @Repository public class UserDao { @Autowired JdbcTemplate jdbcTemplate; Public void updateUser() {jdbctemplate. update("update user set username = 'updateUser '"); } } @Service public class TransactionService { @Autowired private UserDao userDao; @Autowired private BookDao bookDao; public void multiUpdate() { userDao.updateUser(); bookDao.updateBook(); }}Copy the code

Exception demonstration

@Service public class TransactionService { @Autowired private UserDao userDao; @Autowired private BookDao bookDao; public void multiUpdate() { userDao.updateUser(); int i = 12 / 0 ; bookDao.updateBook(); }}Copy the code

Spring transaction is introduced to analyze the — — — — — – PlatformTransactionManager simple introduction

Transaction manager implementation class

Because we are using the database connection pool to access the database, so the transaction manager USES DataSourceTransactionManager.

11.4. Declare Transaction Control with Spring annotations Experiment 2: Test Spring’s declarative transactions

1. Add annotations to methods that require transactions.

*/ @transactional public void multiUpdate() {userdao.updateUser (); int i = 12 / 0 ; bookDao.updateBook(); }Copy the code

Configure the transaction manager driver

<! - the transaction manager - > < bean id = "transactionManager" class = ". Org. Springframework. JDBC datasource. DataSourceTransactionManager "> <property name="dataSource" ref="dataSource"/> </bean>Copy the code

3. Configure transaction annotation drivers

<! -- <tx:annotation-driven/> Turn on annotated transaction driver enable broker transaction-Manager ="transactionManager" configures the transaction manager If the transactionManager id value is transactionManager, the transactionManager property can be omitted --> <tx:annotation-driven />Copy the code

11.5. NoRollbackFor and noRollbackForClassName Test exceptions that do not roll back Experiment 3: noRollbackFor and noRollbackForClassName test exceptions that do not roll back

/** * @transactional indicates that the current method has a transaction <br/> * by default. RuntimeException Run-time exception and run-time child exception. Will roll back the transaction. < br / > * noRollbackFor = Java lang. ArithmeticException. Arithmetic exception class said no rollback transaction < br / > * noRollbackFor = {java.lang.ArithmeticException.class,java.lang.NullPointerException.class}<br/> * NoRollbackForClassName = "Java. Lang. NullPointerException" set which the name of the class of abnormal not rollback transaction < br / > * / @Transactional(noRollbackForClassName="java.lang.NullPointerException") public void multiUpdate() { userDao.updateUser(); // int i = 12 / 0 ; Object object = null; System.out.println( object.toString() ); bookDao.updateBook(); }Copy the code

11.6 customizing Rollback Exceptions Experiment 5 rollbackFor and rollbackForClassName Rollback exceptions

/** * @filenotFoundexception * @Transactional indicates that the current method has a transaction <br/> * Default. RuntimeException Run-time exception and run-time child exception. Will roll back the transaction. < br / > * rollbackFor = FileNotFoundException class Settings when throw FileNotFoundException anomalies, Rollback transaction < br / > * rollbackForClassName = "Java. IO. FileNotFoundException" Settings when thrown FileNotFoundException exception will roll back the transaction < br / > * / @Transactional(rollbackForClassName="java.io.FileNotFoundException") public void multiUpdate() throws FileNotFoundException { userDao.updateUser(); int i = 12 ; if (i == 12) { throw new FileNotFoundException(); } bookDao.updateBook(); }Copy the code

11.7, Transaction read-only property Experiment 4: Test readOnly read-only property

/** * @filenotFoundexception * @Transactional indicates that the current method has a transaction <br/> * Default. RuntimeException Run-time exception and run-time child exception. <br/> * readOnly=false indicates that the current method can perform read operations. You can also perform write operations (referring to SQL statements). <br/> * Modify, add, delete, is write operation, select query statement is read operation. <br/> * readOnly=true Indicates that the current method can only perform query operations. <br/> */ @Transactional(readOnly=true) public void multiUpdate() throws FileNotFoundException { userDao.updateUser(); bookDao.updateBook(); }Copy the code

Error executing modify statement for read-only method.



11.8 Transaction Timeout attribute timeout(in seconds)

/** * @filenotFoundexception * @Transactional indicates that the current method has a transaction <br/> * Default. RuntimeException Run-time exception and run-time child exception. <br/> * timeout=3 Do not execute SQL statements */ @Transactional(timeout=3) public void multiUpdate() throws FileNotFoundException {userDao.updateUser(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } bookDao.updateBook(); }Copy the code

Timeout occurs when execution time exceeds the specified number of seconds:



Propagation of Transaction

What is the propagation behavior of transactions:

When a transaction method is called by another transaction method, you must specify how the transaction should propagate. For example, a method may continue to run in an existing transaction, or it may start a new transaction and run in its own transaction.

The propagation behavior of a transaction can be specified by propagation properties. Spring defines seven types of propagation behavior.

The propagation characteristics of transactions are of the following types:

11.11, Annotation demonstrates transaction propagation feature UserService BookService TransactionService

Experiment 1: Both large and small transaction propagation characteristics are REQUIRED

	@Transactional(propagation = Propagation.REQUIRED)
	public void multlTransaction() {
	@Transactional(propagation = Propagation.REQUIRED)
	public void updateBook() {
@Transactional(propagation=Propagation.REQUIRED)
public void updateUser() {
Copy the code



Experiment 2: Both large and small transactions propagated for REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()
Copy the code

Experiment 3: Large transactions were REQUIRED and small transactions were REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()
Copy the code

Experiment 4: Large transactions are REQUIRED, small 1REQUIRED, and small 2REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRED)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()
Copy the code

Experiment 5: Large transactions are REQUIRED, small 1REQUIRES_NEW, small 2REQUIRED

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser()
Copy the code



XML configuration transaction declaration

Copy the original annotation transaction management project. Remove all @transactional annotations from it.

<? The 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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd "> <! <context:component-scan base-package="com"></context:component-scan> <! -- load the JDBC. The properties attribute configuration file - > < context: the property - placeholder location = "classpath: JDBC. Properties" / > <! - configure the database connection pool - > < bean id = "dataSource" class = "com. Alibaba. Druid. Pool. DruidDataSource" > < property name = "username" value="${user}"/> <property name="password" value="${password}"/> <property name="url" value="${url}"/> <property name="driverClassName" value="${driverClassName}"/> <property name="initialSize" value="${initialSize}" /> <property name="maxActive" value="${maxActive}"/> </bean> <! - configured jdbcTemplate tools - > < bean id = "jdbcTemplate" class = "org. Springframework. JDBC. Core. JdbcTemplate" > < property name="dataSource" ref="dataSource" /> </bean> <! - configuration transaction manager - > < bean id = "transactionManager" class = ". Org. Springframework. JDBC datasource. DataSourceTransactionManager "> <property name="dataSource" ref="dataSource" /> </bean> <! --> <tx:advice ID ="tx_advice" transaction-manager="transactionManager"> < TX: Attributes > <! <tx:method name="updateUser" Propagation ="REQUIRED"/> <! <tx:method name="save*" Propagation ="REQUIRED"/> <tx:method name="update*" propagation="REQUIRES_NEW"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="multlTransaction" propagation="REQUIRES_NEW"/> <! -- <tx:method name="*"/> All methods read-only="true" The rest are query operations. --> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <! < AOP :advisor advice-ref="tx_advice" pointcut="execution(public * com.service.. *Service*.*(..) )"/> </aop:config> </beans>Copy the code