zoukankan      html  css  js  c++  java
  • Spring事务传播行为中可能的坑点

    一、简介

      Spring事务配置及相关说明详见:https://www.cnblogs.com/eric-fang/p/11052304.html。这里说明spring事务的几点注意:

      1、默认只会检查回滚RuntimeException的异常。

      2、@Transactional注解只能作用于public的方法上,默认传播行为 Propagation.REQUIRED

      3、service内部方法之间的调用,不会被spring拦截到,也即不会产生事务

    二、坑点

      主要的坑点就是在嵌套事务上,当service内部方法之间调用的时候,很可能会产生预期之外的效果。例如下例子:

        saveUser保存用户,如果过程出现异常,则执行saveMsg方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class UserServiceImpl implements UserService{
     
        @Autowired
        private UserDao userDao;
        @Autowired
        private MsgDao msgDao;
        @Autowired
        private MsgService msgService;
            @Autowired
            private UserService userService;
     
         
        @Transactional(propagation = Propagation.REQUIRED)
        public void saveUser(User user) throws Exception {
            System.out.println(user.toString());
            try {
                userDao.saveUser(user);
                int i = 1/0;
    //          saveUser2(user);
            } catch (Exception e) {
    //          msgService.saveMsg();
    //                      this.saveMsg();
                userService.saveMsg();
                throw new RuntimeException();
            }
        }
         
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void saveMsg() {
            TbMsg msg = TbMsg.builder().name("xiaocao").msg("xiaoxiao").age(27).build();
            msgDao.saveMsg(msg);
        }
    }

      单元测试,调用saveUser方法,并没有达到想要的效果(saveUser异常,SaveMsg隔离级别是REQUIRES_NEW,理论上应该能入库)。

      失败原因即是上面第一节中说的:同一个service中的方法调用,不会产生新事务。Spring 事务的管理控制,主要是通过AOP的动态代理增强来实现的,目标对象本身并没有任何的事务管理能力,都是通过代理对象动态增强功能去实现事务管理。在同一个service中的方法调用,相当于是目标对象本身的this调用,并没有经过代理对象,所以自然的事务配置的嵌套均无效。

      解决策略:

      1、saveMsg移动到另一个service中,在UserServiceImpl中导入MsgService,saveUser中通过MsgService类去调用。

      2、UserServiceImpl中注入自己,通过注入的自身service进行调用。

  • 相关阅读:
    [51nod] 1088 最长回文子串 #Hash+二分
    [51nod] 1378 夹克老爷的愤怒 #树形DP
    [BZOJ] 2456: mode #众数计数法
    [51nod] 1199 Money out of Thin Air #线段树+DFS序
    [51nod] 1494 选举拉票 #算法设计策略
    [51nod] 1463 找朋友 #离线+扫描线
    [BZOJ] 2733: [HNOI2012]永无乡 #线段树合并+并查集
    [BZOJ] 1012: [JSOI2008]最大数maxnumber
    [Codeforces] E. Lomsat gelral #DSU on Tree
    [BZOJ] 4756: [Usaco2017 Jan]Promotion Counting #线段树合并+权值线段树
  • 原文地址:https://www.cnblogs.com/leeego-123/p/12132640.html
Copyright © 2011-2022 走看看