Spring本地事务应用(问题)

本地事务

     springboot 1.x使用事务需要在引导类上添加@EnableTransactionManagement注解开启事务支持

     springboot 2.x可直接使用@Transactional玩事务,传播行为默认是REQUIRED

springboot2.1开始默认的代理对象变成了cglib,而不是JDK了

注意:

              spring的事务是基于AOP的声明式事务,AOP默认是基于JDK动态代理的(只有AOP代理的对象才可能有事务的功能),所以@Transactional注解必须使用在接口的实现类上,

传播行为问题:

实际样例:在bigSave中有saveSpuDesc方法,两个方法全部加上事务(都是接口重写方法)

理论结果:当bigSave方法执行时,由于传播行为是REQUIRES_NEW所以两个是物质将并没有影响。

实际结果:保存后两个方法都没有执行。

 猜想:他们两个还是同一个事务。并没有分开。

认证(进行断点调试):发现调用该saveSpuDesc方法的对象,并不是代理对象,而是普通的当前类的实例对象。

但是调用bigSave方法的对象却是代理对象。所以bigSave整体是一个事务,里面再怎么加事务都无法执行。

 解决方案:

一、让两个方法在不同的实现类中,通过注入类一个类的对象(这是此对象为代理对象),调用另一个方法,这是就是两个事务之间的事情了。

二、让bigSave方法中需要事务的方法使用代理对象进行调用(基本用不到)

  1. 导入aop的场景依赖:spring-boot-starter-aop

  2. 开启AspectJ的自动代理,同时要暴露代理对象:@EnableAspectJAutoProxy(exposeProxy=true)

  3. 获取代理对象:SpuInfoService proxy = (SpuInfoService) AopContext.currentProxy();

回滚策略:

默认情况下的回滚策略:

  • 运行时异常:不受检异常,没有强制要求try-catch,都会回滚。例如:ArrayOutOfIndex,OutofMemory,NullPointException

  • 编译时异常:受检异常,必须处理,要么try-catch要么throws,都不回滚。例如:FileNotFoundException

可以通过rollbackFor:指定回滚的异常,noRollbackFor :指定不会滚的异常

@Transactional(rollbackFor = FileNotFoundException.class,noRollbackFor = ArithmeticException.class)

超时事务

@Transactional注解,还有一个属性是timeout超时时间,单位是秒。

timeout=3:是指第一个sql开始执行到最后一个sql结束执行之间的间隔时间。

即:超时时间(timeout)是指数据库超时,不是业务超时。

只读事务

@Transactional注解最后一个属性是只读事务属性

如果一个方法标记为readOnly=true事务,则代表该方法只能查询,不能增删改。readOnly默认为false

发布了126 篇原创文章 · 获赞 6 · 访问量 3731

猜你喜欢

转载自blog.csdn.net/qq_40244391/article/details/104183180