美文网首页
Spring事务实践经验之编程式事务VS声明式事务

Spring事务实践经验之编程式事务VS声明式事务

作者: BigfaceMonster | 来源:发表于2022-02-26 15:19 被阅读0次

    背景

    CR时看到在spring中为了减少事务范围,使用编程式事务来替代声明式事务,由此启发研究了下各自的特点。实际场景如下(脱敏代码)

      @Override
      public void resultNotify(AuthModel model) {
            //1.状态检查
            verifyModel verifyModel = repository.queryVerify(model.getVerifyId());
            if (verifyModel == null) {
                LOG.warn("verify record not exist,verifyId:{}", verifyId);
                return;
            }
            //2.更新记录及状态
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    //2.1 更新状态
                    int updateRow = repository.updateVerifyById(verifyModel);
                    if (updateRow != 1) {
                        throw new RuntimeException("update verify result fail");
                    }
                    //2.2 更新状态
                  repository.updateStatus(verifyModel);
                }
            });
        }
    
    

    问题

    • 如何选择使用声明式还是编程式事务

    注意

    Spring声明式事务失效的场景

    • 数据库引擎不支持事务
    • 注解所在类没有被加载为Bean
    • 注解所在方法是非public方法
    • 发生了自调用的情况(经典问题,未经过spring的代理),一种解法
    • 数据源未配置事务管理器
    • 事务的传播行为设置为了Propagation.NOT_SUPPORTED
    • 异常被吃掉了
    • 异常类型不正确,默认只对RuntimeException进行回滚

    分析

    声明式

        @Transactional
        @Override
        public void updatePersonAndUserInfo(Person person,User user) {
            personDao.updatePersonAge(person);
            userDao.updateUserCard(user);
        }
    

    编程式

        @Resource
        private TransactionTemplate transactionTemplate;
    
    @Override
        public void updateUserAndMonsterInfo(Person person, User user) {
            monsterDao.updateMonsterLevel(1, 110);
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    //userDao.updateUserCard(user);
                    updateUserCard(user);
                    personDao.updatePersonAge(person);
                }
            });
        }
    
        private void updateUserCard(User user) {
            userDao.updateUserCard(user);
        }
    

    结论&经验

    声明式事务实现起来更加简单,不用关注过多细节,只需要在接口方法上增加相应声明即可,但很多时候业务逻辑是复杂的,可能涉及多个数据库表的操作,且对各自的事务要求不同,在复杂场景下需要精细的控制事务的粒度和范围时,编程式事务更加灵活。

    相关文章

      网友评论

          本文标题:Spring事务实践经验之编程式事务VS声明式事务

          本文链接:https://www.haomeiwen.com/subject/oxexrrtx.html