本地事务
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方法中需要事务的方法使用代理对象进行调用(基本用不到)
-
导入aop的场景依赖:spring-boot-starter-aop
-
开启AspectJ的自动代理,同时要暴露代理对象:@EnableAspectJAutoProxy(exposeProxy=true)
-
获取代理对象: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