参考文献
Spring事务传播属性和隔离级别 https://www.cnblogs.com/eunice-sun/p/11024584.html
spring事务传播机制总结 https://blog.csdn.net/m18330808841/article/details/109543815
spring boot @Transactional注解事务不回滚不起作用无效 https://blog.csdn.net/zdyueguanyun/article/details/80236401?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
正文
扫盲示例
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-order</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root
App.java
package com.example.demoorder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
UserController.java
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private ServiceA serviceA;
@GetMapping("/a")
public void a() {
serviceA.methodA();
}
}
UserService.java
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper mapper;
//什么都不写时,默认为Propagation.REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
int i = 1 / 0;
}
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
}
}
UserMapper.java
package com.example.demoorder;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserMapper {
@Insert("insert into a (id,name) values (#{id},#{name})")
public void saveA(@Param("id") Integer id, @Param("name") String name);
@Insert("insert into b (id,name) values (#{id},#{name})")
public void saveB(@Param("id") Integer id, @Param("name") String name);
}
ServiceA.java
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
//@Autowired
//private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
//serviceB.methodB();
int i = 1 / 0;
}
}
ServiceB.java
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
}
}
测试:浏览器输入 127.0.0.1:8080/a
a表回滚成功
示例1:
Propagation.REQUIRED
1.如果前面的方法已经创建了事务,那么后面的方法加入这个已存在的事务
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a和b表都回滚成功。
2.如果前面的方法没有创建事务,那么后面的方法会新建一个事务.
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现b表回滚成功,但是a表没有回滚。
示例2:Propagation.SUPPORTS
1如果当前存在事务,则加入当前事务
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前没有事务,就以非事务方法执行
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a和b表都不回滚。
示例3:Propagation.MANDATORY
1当前存在事务,则加入当前事务,
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
methodB();
}
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前事务不存在,则抛出异常。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a表不回滚,methodB()方法进不来,也不打印methodB字符串。
示例4 : Propagation.REQUIRES_NEW
在执行时,不论当前是否存在事务,总是会新建一个事务。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
int i = 1 / 0;
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
}
}
测试:调用methodA()方法,发现a表回滚,b表插入数据库成功,b表不回滚
示例5 :Propagation.NOT_SUPPORTED
在执行时,不论当前是否存在事务,都会以非事务的方式运行。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a表回滚,b表不回滚
示例6 :Propagation.NEVER
就是我这个方法不使用事务,并且调用我的方法也不允许有事务,如果调用我的方法有事务则我直接抛出异常。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.NEVER)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a表回滚,ServiceB的methodB不执行,不打印methodB字符串
示例7 :Propagation.NESTED
如果当前事务不存在,则像 Propagation.REQUIRED开启一个新事物
如果当前事务存在,则在嵌套事务中执行。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a表不回滚,b表回滚
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
try {
serviceB.methodB();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
int i = 1 / 0;
}
}
测试:调用methodA()方法,发现a表不回滚,b表回。因为调用方catch了被调方的异常,所以只有子事务回滚了。
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceA {
@Autowired
private UserMapper mapper;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
System.out.println("methodA");
mapper.saveA(11, "aa");
serviceB.methodB();
int i = 1 / 0;
}
}
package com.example.demoorder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ServiceB {
@Autowired
private UserMapper mapper;
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
System.out.println("methodB");
mapper.saveB(22, "bb");
}
}
测试:调用methodA()方法,发现a表回滚,b表回滚