springBoot service层事务控制的操作

作者:大大大圣 时间:2022-02-01 12:39:40 

springBoot使用事物比较简单,在Application启动类s上添加@EnableTransactionManagement注解,然后在service层的方法上添加@Transactional注解

@Transactional属性

属性类型描述
valueString可选的限定描述符,指定使用的事务管理器
propagationenum: Propagation可选的事务传播行为设置
isolationenum: Isolation可选的事务隔离级别设置
readOnlyboolean读写或只读事务,默认读写
timeoutint (in seconds granularity)事务超时时间设置
rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组

用法:

@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。

另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。

如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

注解在方法上:


@Autowired
private MyBatisDao dao;
@Transactional
@Override
public void insert(Test test) {
dao.insert(test);
throw new RuntimeException("test");//抛出unchecked异常,触发事物,回滚
}

@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void insert(Test test) {
 dao.insert(test);
 //抛出unchecked异常,触发事物,noRollbackFor=RuntimeException.class,不回滚
 throw new RuntimeException("test");
}

@Transactional(propagation=Propagation.NOT_SUPPORTED)
@Override
public void insert(Test test) {
//事物传播行为是PROPAGATION_NOT_SUPPORTED,以非事务方式运行,不会存入数据库
dao.insert(test);
}

注解在类上:当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性


@Transactional
public class MyBatisServiceImpl implements MyBatisService {
@Autowired
private MyBatisDao dao;

@Override
public void insert(Test test) {
 dao.insert(test);
 //抛出unchecked异常,触发事物,回滚
 throw new RuntimeException("test");
}

注意:有时候在开发时往往出现了添加注解后却无法回滚

原因:默认spring事务只在发生未被捕获的 RuntimeException 时才回滚。

spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚

换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被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中的操作也会进行回滚,事务就会起到控制作用。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

来源:https://www.cnblogs.com/tongxuping/p/7650293.html

标签:SpringBoot,Service,事务
0
投稿

猜你喜欢

  • 教你如何使用Java实现WebSocket

    2021-08-22 20:39:02
  • Java实现将每日新闻添加到自己博客中

    2023-02-08 16:20:43
  • 利用C#实现SSLSocket加密通讯的方法详解

    2023-03-01 02:23:05
  • Java使用Log4j记录日志的方法详解

    2022-09-19 01:09:50
  • 详谈java中int和Integer的区别及自动装箱和自动拆箱

    2023-01-18 23:25:20
  • Android自定义密码输入框和数字键盘

    2022-02-04 11:14:00
  • 遍历文件系统目录树的深入理解

    2022-09-15 20:03:46
  • Unity实现鼠标或者手指点击模型播放动画

    2023-11-30 23:06:01
  • Android下的CMD命令之关机重启及重启recovery

    2023-06-20 23:08:21
  • Java 实战项目锤炼之医院门诊收费管理系统的实现流程

    2022-08-10 11:35:08
  • C#配置文件操作类分享

    2022-09-28 11:12:05
  • Java8 使用工厂方法supplyAsync创建CompletableFuture实例

    2023-02-14 03:57:22
  • java9版本特性资源自动关闭的语法增强

    2023-10-30 23:35:24
  • 修改Maven settings.xml 后配置未生效的解决

    2023-07-06 22:17:03
  • 使用mutex实现应用程序单实例运行代码分享

    2023-09-18 22:45:11
  • C#实现发送手机验证码功能

    2022-01-11 18:49:57
  • Java中的final关键字使用方式

    2023-01-16 15:04:25
  • java arrayList遍历的四种方法及Java中ArrayList类的用法

    2023-11-17 17:49:55
  • Android GSYVideoPlayer视频播放器功能的实现

    2022-01-12 23:57:08
  • 解决dubbo错误ip及ip乱入问题的方法

    2023-08-06 17:18:02
  • asp之家 软件编程 m.aspxhome.com