0


@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方法是代理对象执行的,而不是普通方法执行的


本文转载自: https://blog.csdn.net/a1782519342/article/details/125499148
版权归原作者 Arion-ren 所有, 如有侵权,请联系我们删除。

“@Transactional-单元测试中的回滚”的评论:

还没有评论