zoukankan      html  css  js  c++  java
  • [spring transaction],service实现类中非事务方法直接调用自身事务方法导致事务无效的原因

    首先,准备service接口,两个

    public interface AccountService {
    
        public void createAccount(Account account, int throwExpFlag) throws Exception;
    
        public void createAccountShell(Account account, int i) throws Exception;
    
    }
    public interface RoleService {
        
        public void createAccountShell(Account account, int i) throws Exception;
    
    }

    相关impl

    @Service
    public class AccountServiceImpl implements AccountService {
    
        @Resource
        private AccountDAO accountDAO;
        
        @Override
        @Transactional
        public void createAccount(Account account, int throwExpFlag) throws Exception {
            accountDAO.save(account);
            RoleServiceImpl.throwExp(throwExpFlag);
        }
    
        @Override
        public void createAccountShell(Account account, int i) throws Exception {
            this.createAccount(account, i);
        }
    
    }
    @Service
    public class RoleServiceImpl implements RoleService {
    
        @Autowired
        AccountService accountService;
        
        public static void throwExp(int throwExpFlag) throws Exception {
            if (throwExpFlag == 0) {
                throw new RuntimeException("<< rollback transaction >>");
            } else if (throwExpFlag != 1) {
                throw new Exception("<< do not rollback transaction >>");
            }
        }
    
        @Override
        public void createAccountShell(Account account, int i) throws Exception {
            accountService.createAccount(account, i);        
        }
    
    }

    测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration({"classpath:spring/spring-dao.xml", "classpath:spring/spring-service.xml"})
    public class ServiceTransactionTest extends TestCase {
    
            public static Account account;
    
            static {
                    account = new Account();
            account.setId(779);
            account.setUsername("779 USER");
            account.setPassword("0123456");
            }
    
        @Autowired
        AccountService accountService;
        
        @Autowired
        RoleService roleService;
        
        @Test
        public void test_1() throws Exception {
            this.accountService.createAccount(account, 0);
        }
    
            @Test
        public void test_2() throws Exception {
            this.accountService.createAccountShell(account, 0);
        }
    
            @Test
        public void test_3() throws Exception {
            roleService.createAccountShell(account, 0);
        }
    
    }

    (一)对测试类的test_1方法进行单元测试时,由于AccountServiceImpl.createAccount方法显示配置了事务(@Transactional),所以spring正常接管事务。

    (二)对测试类的test_2方法进行单元测试时,AccountServiceImpl.createAccountShell方法并没有显示配置事务,但其却调用了AccountServiceImpl.createAccount方法(已配事务)。然并卵,当抛出RuntimeException时,没有rollback,说明spring没有接管事务。(猜测原因:AccountServiceImpl.createAccountShell 被显示调用时,spring是知道的,但由于AccountServiceImpl.createAccountShell没有显示配置事务,spring并没有对此进行事务的管理,在AccountServiceImpl.createAccountShell内部虽然调用了配置了事务的createAccount方法,但spring并不知道或无法确定事务上下文,所以结果是并没有因为抛出的运行时异常而进行rollback)。

    (三)测试test_3,虽然RoleServiceImpl.createAccountShell同样没有配置事务,但抛出RuntimeException时,spring接管了事务并rollback。(猜测原因:虽然RoleServiceImpl.createAccountShell没有配置事务,但其内部调用另一个service实例的方法,即AccountService.createAccount时,spring对此是获知的,又因为AccountServiceImpl.createAccount显示配置了事务,所以spring接管了事务)。

    (四)如果在AccountServiceImpl.createAccountShell配置了事务,那么在执行test_2时,spring是可以接管事务的。

  • 相关阅读:
    dsu on tree题表
    [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)
    [BZOJ3757]苹果树(树上莫队)
    [BZOJ3585]mex(莫队+分块)
    Prufer codes与Generalized Cayley's Formula
    [luogu4459][BJOI2018]双人猜数游戏(DP)
    [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)
    [BZOJ5291][BJOI2018]链上二次求和(线段树)
    [luogu4389]付公主的背包(多项式exp)
    [CF1086E]Beautiful Matrix(容斥+DP+树状数组)
  • 原文地址:https://www.cnblogs.com/bgo-tech/p/6611570.html
Copyright © 2011-2022 走看看