• [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是可以接管事务的。

  • 相关阅读:
    2020最新JavaScript开发必须知道的41个技巧,你会几个?
    Vue项目上线要做哪些优化?面试必学
    javascript 关于dom节点操作的增删改查
    uniapp 上拉加载下拉刷新
    移动WEB适配布局
    微信小程序中封装网络请求方法
    react兄弟组件传值
    【python】Mutilindex多层索引的取值
    【python】通过Mutilindex生成二维表数据
    【python】python vs Excel ( 如何通过loc与iloc函数处理Excel数据)
  • 原文地址:https://www.cnblogs.com/bgo-tech/p/6611570.html
Copyright © 2020-2023  润新知