springBoot service层事务控制的操作
springBoot使用事物比较简单,在Application启动类s上添加@EnableTransactionManagement注解,然后在service层的方法上添加@Transactional注解
@Transactional属性
用法:
@Transactional可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有public方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然@Transactional注解可以作用于接口、接口方法、类以及类方法上,但是Spring建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。
另外,@Transactional注解应该只被应用到public方法上,这是由SpringAOP的本质决定的。
如果你在protected、private或者默认可见性的方法上使用@Transactional注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
注解在方法上:
@Autowired privateMyBatisDaodao; @Transactional @Override publicvoidinsert(Testtest){ dao.insert(test); thrownewRuntimeException("test");//抛出unchecked异常,触发事物,回滚 }
@Transactional(noRollbackFor=RuntimeException.class) @Override publicvoidinsert(Testtest){ dao.insert(test); //抛出unchecked异常,触发事物,noRollbackFor=RuntimeException.class,不回滚 thrownewRuntimeException("test"); }
@Transactional(propagation=Propagation.NOT_SUPPORTED) @Override publicvoidinsert(Testtest){ //事物传播行为是PROPAGATION_NOT_SUPPORTED,以非事务方式运行,不会存入数据库 dao.insert(test); }
注解在类上:当作用于类上时,该类的所有public方法将都具有该类型的事务属性
@Transactional publicclassMyBatisServiceImplimplementsMyBatisService{ @Autowired privateMyBatisDaodao; @Override publicvoidinsert(Testtest){ dao.insert(test); //抛出unchecked异常,触发事物,回滚 thrownewRuntimeException("test"); }
注意:有时候在开发时往往出现了添加注解后却无法回滚
原因:默认spring事务只在发生未被捕获的RuntimeException时才回滚。
springaop异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获RuntimeException的异常,但可以通过配置来捕获特定的异常并回滚
换句话说在service的方法中不使用trycatch或者在catch中最后加上thrownewruntimeexcetpion(),这样程序异常时才能被aop捕获进而回滚。
解决方案:
1.在service层方法抛出RuntimeException异常(如在Catch中需要抛出自定义的异常则只需自定义异常继承RuntimeException即可),并继续捕获和处理这个异常。
2.在service层方法的catch语句中增加:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
语句,手动回滚,这样上层就无需去处理异常。
补充:springboot多个service互相调用的事务处理
今天,想在一个service的方法A中,调用另一个service的方法B,方法A和方法B均存在数据库插入操作,并且@Transaction注解也都加了,但是当B方法中抛出异常时,A中的插入语句还是能够执行成功。
注解配置如下:
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
百思不得其解,再查找了相关资料后,问题还是出在@Transaction注解的配置上,需要配置异常回滚。
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
这样,当B方法中抛出异常时,A中的操作也会进行回滚,事务就会起到控制作用。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。