@Transactional-单元测试中的回滚

1.问题1

今天在JUnit单元测试中测试接口时,突然发现idea写入数据库成功,但是数据库中没有数据

@Slf4j
@Rollback
@Transactional
class ShippingServiceImplTest extends MallApplicationTests {

    @Autowired
    private ShippingService shippingService;

    private Integer uid = 1;

    @Test
    public void add() {
        ShippingForm form = new ShippingForm();
        form.setReceiverName("Arion");
        form.setReceiverAddress("江苏南京");
        form.setReceiverCity("北京");
        form.setReceiverMobile("12212345678");
        form.setReceiverPhone("010123456");
        form.setReceiverProvince("北京");
        form.setReceiverDistrict("海淀区");
        form.setReceiverZip("000000");
        ResponseVo<Map<String, Integer>> responseVo = shippingService.add(uid, form);
        log.info("result={}", responseVo);
    }

  
}

去掉@Rollback注解后,idea中事务正常执行,mysql数据库中依然是没有数据的,查看日志发现

[main] INFO  o.s.t.c.t.TransactionContext - Rolled back transaction for test:

明显事务虽然执行成功了但是回滚了,仔细一看问题出在@Transactional,spring支持声明式事务,通过AOP实现实现用户操作和具体的事务解耦,加上该注解后,方法执行前创建一个事务,当方法结束后回滚该事务,这就是为什么idea中事务是执行成功的,最后数据库找中没有数据。

需要注意的是:
事务回滚后主键id不会随着事务的回滚而删除

2.注解失效

执行如下的test方法时,不会报错,证明方法a的注解是没有生效的。

原因在于spring中的@Transactional注解是通过AOP的机制来实现的,首先是产生一个代理对象,然而在执行父类的a方法时,是通过被代理的对象(普通对象)行的,也就是所谓的普通对象,然而普通对象在执行时不会判断方法上是否有事务的注解,因此不生效。

2.1 解决办法1-拆分类

将要执行的a方法单独拆成一个类,然后通过自动注入来调用,因为单独拆分的这个类也是有事务的,所以要进行AOP生成代理对象,最终容器中放的是代理对象,自动注入拿到的bean也是被代理后的,因此可以执行事务。

 2.2 直接通过代理对象执行a方法

 因为这个时候执行的a方法是代理对象执行的,而不是普通方法执行的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值