Spring原理解读——事务传播行为
写在前面
不要使用junit等测试方法测试事务,spring会自动回滚事务
不要把不同事务写在同一个类里,这样无法打到事务嵌套的测试效果
请手动回滚,不要尝试向上层抛出异常
准备工作
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
一个工具类
public class TransactionUtil {
public static void manaul(){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
表结构
create table user
(
id bigint not null comment '主键'
primary key,
username varchar(40) null comment '用户名',
password varchar(100) null comment '密码',
locked tinyint(1) default 0 null comment '是否锁定',
disable tinyint(1) default 0 null comment '禁用'
);
一个Controller
@RestController
@RequestMapping("/testController")
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/testMethod")
public void testMethod(){
testService.testMethod();
}
}
两个Service
@Service
public class TestService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TestService2 testMethod2;
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void testMethod() {
testMethod2.testMethod2();
jdbcTemplate.update("insert into fastkdm.user (id, username, password) VALUE (2,'transaction_test','111111')");
manaul();
}
}
@Service
public class TestService2 {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void testMethod2(){
jdbcTemplate.update("insert into fastkdm.user (id, username, password) VALUE (3,'transaction_test2','111111')");
}
}
1、REQUIRED
默认传播行为
使用当前的事务,如果不存在,就新建一个事务
结果
内外层属于同一事务,任意一层回滚会导致整体回滚
2、REQUIRES_NEW
内层新建一个事务
如果外层事务存在,则先将外层挂起,等内层执行完再执行外层
结果
内外层属于不同事务,层与层之间的事务互不影响
3、NESTED
内层新建一个嵌套事务,隶属于外层
如果外层事务存在,先提交外层事务,然后记录外层操作点,再执行内层,内层失败返回操作点
结果
内层事务嵌套在外层事务里,内层回滚不会影响外层,外层回滚会连同内层一起
4、MANDATORY
外层必须有事务
5、NEVER
外层必须没事务
6、SUPPORTS
内层使用的事务传播类型取决于外层,没有则不使用
7、NOT_SUPPORT
不论外层有没有事务,内层都不由事务控制