@Transaction使用注意事项

准备工作:

创建两张mysql表,id设置为自增。test1表有id和name字段,test2有id和name字段(且name字段不为空)

 

测试一:

controller层
@GetMapping("/test")
public Result test(String userName) {
    return service.test(userName);
}

 

serviceImpl层

@Override
@Transactional(rollbackFor = Exception.class)
public Result test(String userName) {
    testMapper.saveTest1("userName1");--没有回滚
    try {
        saveTest2(userName);
    } catch (Exception e) {
        log.warn("test报错{}", e.getMessage());
    }
    return Result.succeed("成功");
}

@Transactional(rollbackFor = Exception.class)
public void saveTest2(String userName) {
    testMapper.saveTest2(userName);--因为name字段设置了不能为空,所以这条数据没有添加成功
}

 

mapper层

@Insert("insert into test1(name) values(#{userName})")
void saveTest1(String userName);

@Insert("insert into test2(name) values(#{userName})")
void saveTest2(String userName);

调用/test接口,不传参数,最终结果:

test1表里有两条数据,test2表里没有数据,也就是事务没有回滚。

test1表数据如下

 

 

 

   

测试二:

controller层
@GetMapping("/test1")
public Result test1(String userName) {
    return service.test1(userName);
}

 

serviceImpl层

@Override
@Transactional(rollbackFor = Exception.class)
public Result test1(String userName) {
    testMapper.saveTest1("userName1");
    try {
        otherServiceImpl.saveTest2(userName); --回滚了
    } catch (Exception e) {
        log.warn("test报错{}", e.getMessage());
    }
    return Result.succeed("成功");
}

 

新建一个otherServiceImpl类,把测试一的saveTest2方法直接挪过来

@Transactional(rollbackFor = Exception.class)
public void saveTest2(String userName) {
    testMapper.saveTest2(userName); --回滚了
}

 

mapper层

@Insert("insert into test1(name) values(#{userName})")
void saveTest1(String userName);

@Insert("insert into test2(name) values(#{userName})")
void saveTest2(String userName);

调用/test1接口,不传参数,最终结果:

test1和test2表里都没有数据,也就是saveTest2方法被移到另一个service类的时候,代表事务回滚了。

 

 测试一和测试二得出结论:

在同一个类中,一个方法调用另一个带@Transaction注解的方法时,方法上的@Transaction注解不会生效。

解决这个问题,有一个简单的办法,就是新建一个类,将第二个方法移到新写的类里,此时@Transaction注解就可以生效了。

 

测试三:

controller层
@GetMapping("/test2")
public Result test2(String userName) {
    return service.test2(userName);
}

 

serviceImpl层

@Override
@Transactional(rollbackFor = Exception.class)
public Result test2(String userName) {
    testMapper.saveTest1("userName1");
    try {
        saveTest2(userName);
    } catch (Exception e) {
        log.warn("test报错{}", e.getMessage());
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
    return Result.succeed("成功");
}

@Transactional(rollbackFor = Exception.class)
public void saveTest2(String userName) {
    testMapper.saveTest2(userName);
}

 

mapper层

@Insert("insert into test1(name) values(#{userName})")
void saveTest1(String userName);

@Insert("insert into test2(name) values(#{userName})")
void saveTest2(String userName);

调用/test3接口,不传参数,最终结果:

test1和test2表里都没有数据。

即:在同一个类中,一个方法调用另一个带@Transaction注解的方法时,加上“TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();”,方法上的@Transaction注解就会生效。

 

posted @ 2021-10-13 19:29  素净  阅读(341)  评论(0编辑  收藏  举报