service层@Transactional事务控制使用以及注意

12 篇文章 0 订阅

 

@Service
@Transactional
public class CeshiService {


    @Autowired
    LoginFeignClient loginFeignClient;

    @Transactional(rollbackFor = Exception.class)
    public void test(){
        User user=null;
        //try {
            log.info("ceshi transactional is 1");
            user=loginFeignClient.test1().getData();
            throw  new RuntimeException();
            //log.info("ceshi transactional is 2");
           // loginFeignClient.test();
       // }catch (Exception e){
        //    throw new Exception(e.getLocalizedMessage());
       // }

    }
}


上述就是一个事务的service,当获取到throw的exception时执行rollback;

 

1.service中是通过feign调用远程服务时,上述写法是无法回滚的,只有repository在本地代码处理才可以,因为db提供了回滚处理。

2.如果是feign远程调用,又想使用事务,则需要进行逆服务处理,需要获取异常时,手动调用逆服务处理

3.非事务声明方法调用事务声明方法,则事务失效。使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B(不管B是否public还是private),但A没有声明注解事务,而B有。则外部调用A之后,B的事务是不会起作用的。(经常在这里出错)

针对这种情况,进行了实例测试:

@Service
@Slf4j
public class TransTestService {

    @Autowired
    QueueAppointRecordMapper  queueAppointRecordMapper ;

    public void noTrans(){
        QueueAppointRecordVo recordVo = new QueueAppointRecordVo();
        recordVo.setId(6549928413648389141L);
        List<QueueAppointRecord> list1 = queueAppointRecordMapper.getAppointRecordById(recordVo);
        log.info("record status1:{}", list1.get(0).getStatus());
        QueueAppointRecordVo vo = new QueueAppointRecordVo() ;
        vo.setId(6549928413648389141L);
        vo.setStatus("R07");
        queueAppointRecordMapper.updateStatus(vo) ;
        log.info("noTrans,status:R07");
        trans();
    }

    @Transactional
    public void trans(){
        QueueAppointRecordVo vo = new QueueAppointRecordVo() ;
        vo.setId(6549928413648389141L);
        vo.setStatus("R09");
        queueAppointRecordMapper.updateStatus(vo) ;
        log.info("trans,status:R09");
        throw new RuntimeException() ;
    }
}

没有@Transactional标签的方法notrans调用有@Transactional的方法trans方法,

这条记录原始状态R01,经过程序后依次变更为R07  R09,虽然trans事务方法遇到了runtimeException,最后查数据库的状态也是R09。也就说明trans方法的事务是没有起作用的。

4.一个service中声明事务方法,调用了另外一个service中的声明事务方法,则被调用的方法事务也还起作用,事务不太建议放到2个见service中。下面的例子,下面的事务是起作用的,跟上面第3条写的注意区分:

同一工程内,controller中调用第一个service声明了Transactional,service中再调用其他service中非声明的事务,如果遇到RunTimeException则还是事务回滚的,但是尽量使用事务的方法,都加上Transactional声明

 

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值