zoukankan      html  css  js  c++  java
  • @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.saveTest1("userName2");--没有回滚
        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);

    调用/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.saveTest1("userName2");
        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.saveTest1("userName2");
        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注解就会生效。

  • 相关阅读:
    为什么要用webUI?
    探索WebKit内核(一)------ 菜鸟起步
    主进程退出的时候,杀死所有子进程
    那两年炼就的Android内功修养
    飞鸽---局域网聊天软件攻防战
    如何利用Fluxion诱惑目标用户获取WPA密码
    性能测试:CPU内存,硬盘IO读写,带宽速度,UnixBench
    解决maven编译错误:程序包com.sun.xml.internal.ws.spi不存在
    Apache-Flink深度解析-DataStream-Connectors之Kafka
    linux下find(文件查找)命令的用法总结
  • 原文地址:https://www.cnblogs.com/supiaopiao/p/15403916.html
Copyright © 2011-2022 走看看