一、七种事务传播属性
Spring可以通过注解@Transactional来为业务逻辑层的方法(调用DAO完成持久化动作)添加事务能力。
默认是Propagation.REQUIRED。
Propagation.REQUIRED | 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。 |
Propagation.SUPPORTS | 如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。 |
Propagation.MANDATORY | 如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。 |
Propagation.REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
Propagation.NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
Propagation.NEVER | 以非事务的方式运行,如果当前存在事务,则抛出异常。 |
Propagation.NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 |
二、传播属性示例
通过几个例子理解REQUIRED、REQUIRES_NEW、NESTED 的使用(注意try...catch的使用)
DemoDao操作数据库,辅助查看测试结果。
1.Springboot项目部分配置
ServiceA
@Service
public class ServiceA {
@Autowired
private DemoDao demoDao;
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void testTransactional() {
Demo demo = new Demo(2, "李四");
demoDao.insert(demo);
try {
serviceB.testTransactional();
} catch (Exception e) {
e.printStackTrace();
}
// throw new RuntimeException("a");
}
}
ServiceB
@Service
public class ServiceB {
@Autowired
private DemoDao demoDao;
@Transactional(propagation = Propagation.REQUIRED)
public void testTransactional() {
Demo demo = new Demo(3, "王五");
demoDao.insert(demo);
throw new RuntimeException("b");
}
}
application.properties
server.port=8080
# 数据源
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 指定mybatis配置文件位置
mybatis.config-location=classpath:mybatis-config.xml
mybatis.mapper-locations=classpath*:mapper/*Mapper.xml
#打印sql
logging.level.com.asyf.demo.dao=debug
mybatis-config.xml配置打印日志 -> 查看事物提交日志
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>
<settings>
<!-- 打印日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 全局参数 -->
<!-- 使全局的映射器启用或禁用缓存。 -->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
注意:通过这个配置看不到回滚操作日志,使用logback设置日志级别DEBUG能看到
设置 logback-spring.xml <root level="DEBUG">... </root> 可以看见 Rolling back JDBC transaction on Connection 日志
2.通过表格的形式展示不同的异常状态,对结果的影响(一定要结合try...catch) :
ServiceA.testTransactional()以PROPAGATION_REQUIRED修饰;
ServiceB.testTransactional()以表格中三种方式修饰;
异常状态 | REQUIRED | REQUIRES_NEW | NESTED |
a正常 b正常 |
a与b一起提交 | b先提交,a再提交 | a与b一起提交 |
a正常 b异常 |
a与b一起回滚 异常:Transaction rolled back because it has been marked as rollback-only |
b回滚,a提交(如果a不捕获异常都回滚) | b回滚,a提交 |
a异常 b正常 |
a与b一起回滚 | a回滚,b提交 | a与b一起回滚 |
a异常 b异常 |
a与b一起回滚 | b先回滚,a再回滚 | a与b一起回滚 |
3.如何查看事务提交顺序
注意sqlSession对象和committing关键字
a正常b正常REQUIRES_NEW条件下日志 -> b先提交a再提交
三、参考
https://blog.csdn.net/yanxin1213/article/details/100582643
https://blog.csdn.net/weixin_39625809/article/details/80707695