SpringBoot事务传播属性测试

一、七种事务传播属性

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

猜你喜欢

转载自blog.csdn.net/cs373616511/article/details/106997596