springBoot service层事务控制的操作

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

@Transactional属性

属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自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中的操作也会进行回滚,事务就会起到控制作用。

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

(0)

相关推荐

  • 详解SpringBoot 解决拦截器注入Service为空问题

    一.自定义拦截器实现 HandlerInterceptor 接口 /** * * Created by zhh on 2018/04/20. */ public class MyInterceptor implements HandlerInterceptor { @Autowired private NetworkProxyInfoService networkProxyInfoService; @Override public void afterCompletion(HttpServlet

  • SpringBoot使用CXF集成WebService的方法

    1.写在前面 WebService 对我来说既熟悉又陌生,已经将近六七年没有看到过他了, 具体的介绍我就不多少了, 想了解的百度百科下说的很详细. 之所以突然研究WebService是接到一个需求要去给 XX 项目做一个适配层,他们原有系统是使用webservice做的,所以-- 那我们就来看看,这一个古老的技术如何和如今最流行的框架SpringBoot进行结合. 2.SpringBoot 集成WebService 2.1 导入依赖 compile('org.springframework.bo

  • idea显示springboot多服务启动界面service操作

    如果是多模块的微服务,idea提供了一个可以多服务启动的界面services,如果你的项目里没看到这个界面: 那么你需要在顶级的maven工程中找到这个配置,然后找到 component name="RunDashboard"这个节点整个替换掉: <component name="RunDashboard"> <option name="configurationTypes"> <set> <option

  • springboot整合cxf发布webservice以及调用的方法

    webservice性能不高,但是现在好多公司还是在用,恰好今天在开发的时候对接项目组需要使用到webservice下面来说下简单的案例应用 首先老规矩:引入jar包 <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.1.11</version> &

  • SpringBoot集成shiro,MyRealm中无法@Autowired注入Service的问题

    网上说了很多诸如是Spring加载顺序,shiroFilter在Spring自动装配bean之前的问题,其实也有可能忽略如下低级错误. 在ShiroConfiguration中要使用@Bean在ApplicationContext注入MyRealm,不能直接new对象. 道理和Controller中调用Service一样,都要是SpringBean,不能自己new. 错误方式: @Bean(name = "securityManager") public SecurityManager

  • SpringBoot Service和Dao的编写详解

    本文主要介绍了SpringBoot Service和Dao的编写详解,分享给大家,具体如下: 效果图 配置环境 创建数据库 数据库中文编码 建表 create table `student` ( `id` int(11) Not NULL AUTO_INCREMENT COMMENT '主键自增id', `name` varchar(250) NOT NULL DEFAULT ' ' COMMENT '姓名', PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT C

  • springBoot service层事务控制的操作

    springBoot使用事物比较简单,在Application启动类s上添加@EnableTransactionManagement注解,然后在service层的方法上添加@Transactional注解 @Transactional属性 属性 类型 描述 value String 可选的限定描述符,指定使用的事务管理器 propagation enum: Propagation 可选的事务传播行为设置 isolation enum: Isolation 可选的事务隔离级别设置 readOnly

  • SpringBoot在自定义类中调用service层等Spring其他层操作

    背景: 做了一个TCP服务器来接入智能设备,然后需要将设备实时发送的定位等关键信息存储到数据库. 为了考虑将来可能对外提供rest接口,采用将TCP服务器集成到SpringBoot框架,当然,也是为了能最快利用mybatis框架实现数据访问,然后依次解决了如何启动,如何注销等各种问题,然后在TCP服务器消息处理时,需要写数据库,直接调用DAO层,编译报错. 改为调用Service层,编译正常,运行到调用的地方,报空指针异常,跟踪到异常位置,发现service为空,也就是按照之前controlle

  • 关于controller的异常处理及service层的事务控制方式

    目录 controller异常处理及service层的事务控制 controller层Exception异常事务回滚失效问题 Spring的@Transactional源码中写道 测试① 测试② 测试③ 测试④ controller异常处理及service层的事务控制 最近写代码涉及到一些事务,上午终于把代码给理顺了,之前不太清楚在哪里做异常处理,导致代码遍地try-catch,相当难看. 还是基于controller-service-dao三层来写代码,从入口开始,controller层的方法

  • SpringBoot持久化层操作支持技巧

    SpringBoot的持久化层可以是Spring内置的轻量级JdbcTemplate.也可以是Hibernate或Mybatis等等,只需要在在工程pom.xml文件中添加对应的依赖就可以了. 新建工程我们能发现,SpringBoot对数据库操作的支持有以下几种: 可见SpringBoot对各种的支持还是挺多的. 入正题.看看对SQL的支持.主要选了比较传统/流行/有前景的4个进行操作: 均是采用mysql. 所以应该添加对mysql操作的依赖: <!--MySQL--> <depend

  • SpringBoot数据层测试事务回滚的实现流程

    目录 数据层测试事务回滚 dao下 pojo对象 service 测试用例数据设定 数据层测试事务回滚 pom.xml导入对应的一些坐标,mysql,Mp,等 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </depende

  • SpringBoot集成JPA持久层框架,简化数据库操作

    目录 与SpringBoot2.0整合 1.核心依赖 2.配置文件 3.实体类对象 4.JPA框架的用法 5.封装一个服务层逻辑 测试代码块 源代码地址 与SpringBoot2.0整合 1.核心依赖 <!-- JPA框架 --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-jpa<

  • 详解SpringBoot中JdbcTemplate的事务控制

    目录 前言 原生Jdbc的事务控制 Spring的声明式事务控制 尝试JdbcTemplate的事务控制 TransactionTemplate的编程式事务控制 前言 JdbcTemplate是spring-jdbc提供的数据库核心操作类,那对JdbcTemplate进行事务控制呢? 我的环境:spring-boot-2.1.3,druid-1.1.3. 原生Jdbc的事务控制 即,批处理+自动提交的控制方式, public static void demo(String[] args) thr

  • spring在service层的方法报错事务不会回滚的解决

    目录 spring在service层方法报错事务不会回滚 解决方法 service手动回滚问题 spring在service层方法报错事务不会回滚 @Transactional(rollbackFor = {Exception.class}) public void insertData() throws Exception {     // 业务代码1     business1();          // 业务代码2     business2();          // 业务代码3  

  • Spring框架 XML配置事务控制的步骤操作

    目录 基于 XML 的声明式事务控制 1.环境搭建 2.创建 spring 的配置文件并导入约束 3.准备数据库表和实体类 4.业务层接口与实现类 5.数据访问层接口与实现类 6.配置c3p0数据源/业务层/数据访问层 7.配置事务管理器 8.配置事务的通知 9.配置 AOP 切入点表达式 10.配置切入点表达式和事务通知的对应关系 基于 XML 的声明式事务控制 1.环境搭建 拷贝必要的 jar 包到工程的 lib 目录 2.创建 spring 的配置文件并导入约束 这里直接给出本次测试的全部

  • Springboot通过aop实现事务控制过程解析

    spring的事务控制本质上是通过aop实现的. 在springboot中使用时,可以通过注解@Transactional进行类或者方法级别的事务控制,也可以自己通过spring提供的事务管理器手动控制事务 一. @Transactional注解进行进行类或者方法级别的事务控制 不需要进行特别的设置,按照正常的配置整合spring和mybatis后,在需要进行事务控制的类上或者方法上加上 @Transactional注解,即可对其进行事务控制. 二.手动控制事务 当需要在一个方法的内部进行事务控

随机推荐