zoukankan      html  css  js  c++  java
  • @Transactional注解为什么不生效

    一、背景

    • 方法添加了@Transactional注解,为什么事务不生效

    二、步骤

    • 测试用表结构
    CREATE TABLE `test_aop` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(100) DEFAULT NULL,
        PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    • 事务方法所在类
    @Component
    @Slf4j
    public class AopDataService {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        private AopDataService aopDataService;
    
        // 写入数据
        @Transactional
        public void insert(String value) {
            jdbcTemplate.update("insert into test_aop(name) values('" + value + "')");
        }
    
        // 写入数据后抛异常
        @Transactional
        public void insertAndRollback(String value) {
            log.info("insertAndRollback {}", value);
            jdbcTemplate.update("insert into test_aop(name) values('" + value + "')");
            throw new RuntimeException();
        }
    
        // 使用this调用事务方法
        public void invokeMethod() {
    
            try {
    
                this.insertAndRollback("invokeMethod");
    
                // 这里的this就是AopDataService,不是代理对象。
                // 所以调用的insertAndRollback方式是原生方法,不是@Transactional注解代理后的对象
    
            } catch (RuntimeException ex) {
                log.warn("Catch an Exception in invokeMethod()");
            }
        }
    
        // 使用this.aopDataService调用事务方法
        public void invokeMethodAutowired() {
    
            try {
    
                this.aopDataService.insertAndRollback("invokeMethodAutowired");
                // this.aopDataService 代理对象,事务生效
    
            } catch (RuntimeException ex) {
                log.error("Catch an Exception in invokeMethodAutowired()");
            }
        }
    
        // 使用getBean调用事务方法
        public void invokeMethodGetBean() {
    
            try {
    
                AopDataService aopDataService = SpringUtil.getBean("aopDataService", AopDataService.class);
                aopDataService.insertAndRollback("invokeMethodGetBean");
    
                // aopDataService 代理对象,事务生效
    
            } catch (RuntimeException ex) {
                log.warn("Catch an Exception in invokeMethodGetBean()");
            }
        }
    
    }
    • 调用事务方法单元测试
      @Autowired
        private AopDataService aopDataService;
    
        // 写入成功(this.aopDataService是代理对象)
        @Test
        public void insert() {
    
            this.aopDataService.insert("insert");
        }
    
        // 抛异常,数据写入不成功(this.aopDataService是代理对象)
        @Test
        public void insertAndRollback() {
    
            this.aopDataService.insertAndRollback("insertAndRollback");
        }
    
        // 抛异常,数据写入成功(invokeMethod方法内未使用AopDataService代理对象)
        @Test
        public void invokeMethod() {
    
            this.aopDataService.invokeMethod();
        }
    
        // 抛异常,数据写入不成功(invokeMethodAutowired方法内使用了AopDataService代理对象)
        @Test
        public void invokeMethodAutowired() {
    
            this.aopDataService.invokeMethodAutowired();
        }
    
        // 抛异常,数据写入不成功(invokeMethodGetBean方法内使用了AopDataService代理对象)
        @Test
        public void invokeMethodGetBean() {
    
            this.aopDataService.invokeMethodGetBean();
        }

    三、总结&问题

    • invokeMethod通过 this方式调用insertAndRollback方法,该方法抛异常但是写入成功,原因是
      这里的this就是 AopDataService,不是代理对象。 
      所以调用的insertAndRollback方式是原生方法,不是@Transactional注解代理后的对象
    • invokeMethodAutowired、invokeMethodGetBean调用成功是因为都使用的AopDataService代理对象
  • 相关阅读:
    Spring 3.0 发布候选版 3 已经可用!
    NetBeans IDE 6.8 正式版发布!
    250g铜版纸 打印扑克?
    一键安装python
    京东商城副总裁李曦:大数据和电子商务_行业信息化_IT商业新闻网
    9.29的北京-》杭州的票怎么现在网上还没有可以预订呢。。。
    运动服火鸟2代三叶草运动服SWIM CLUB 1976款游泳秋装男款海马淘宝网
    无锡巨人网络科技有限公司简介20120411
    李国庆送的国旗太小了,没动力买东西
    虽然不信god,但是技术上还是算是有信yan的人吧
  • 原文地址:https://www.cnblogs.com/gossip/p/14280772.html
Copyright © 2011-2022 走看看