解决SpringBoot中使用@Transactional注解遇到的问题

 更新时间:2021年09月22日 11:42:26   作者:f0cf20ca7354  
这篇文章主要介绍了SpringBoot中使用@Transactional注解遇到的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用@Transactional注解遇到的问题

1、不建议在接口上添加@Transactional注解

一般在service类标签上添加@Transactional即可

2、@Transactional注解

只能应用到public可见度的方法上。如果应用到protected、private或者package可见度的方法上时,不会报错,但事务也不会起作用

3、默认情况下

spring会对uncheck异常进行事务回滚的;如果是checked异常则不会回滚,可添加注解 @Transactional(rollbackFor=Exception.class) 是的checked异常回滚。

  • uncheck异常:java里面将派生于Error或者RuntimeException(比如空指针,1/0)的异常
  • checked异常:其他继承自java.lang.Exception得异常统称为Checked Exception,如IOException、TimeoutException等

4、数据库引擎需要支持事务管理

如果是mysql,注意表要使用事务的引擎,比如innodb,如果是myisam,事务不会起作用的

5、同一类中methodA()方法

没有@Transactional 注解,在其内部调用有@Transactional 注解的方法,有@Transactional 注解的方法methodB()的事务被忽略,不会开启新的事务,也不会发生回滚。例如:

@Service
public class TransactionService {
public void methodA(){
    this.methodB();
}
@Transactional
public void methodB(){
}
}

原因:Spring采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理。

详解:Spring的事务管理是通过AOP实现的,其AOP的实现对于非final类是通过cglib这种方式,即生成当前类的一个子类作为代理类,然后在调用其下的方法时,会判断这个方法有没有@Transactional注解,如果有的话,则会开启一个新的事务,并通过动态代理实现事务管理(拦截方法调用,执行事务等切面)。

当methodA()中调用methodB()时,并不是使用的代理对象,而是普通的javabean,从而导致this.methodB()时也不是代码对象,从而导致@Transactional失败,即发现methodA()上并没有@Transactional注解,所以整个AOP代理过程(事务管理)不会发生。

解决办法:

1、把这两个方法分开到不同的类中;

2、把注解@Transactional加到类名上面去;

3、把注解@Transactional加到methodA()方法上,methodB()不添加注解,在调用methodB()时两个方法的事务都会生效,因为methodA()默认的事务传播属性为PROPAGATION_REQUIRED,此时methodB()会加入到methodA()中

@Service
public class TransactionService {
@Transactional
public void methodA(){
    this.methodB();
}
public void methodB(){
}
}

4、获取本对象的代理对象,再进行调用。具体操作如:

  • Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy="true"/>
  • 在TransactionService 中,用(transactionService )(AopContext.currentProxy()),获取到TransactionService 的代理类,再调用事务方法,强行经过代理类,激活事务切面。

springboot 注解transactional失效

1、在方法中捕获了异常

那么该方法事务不会回滚。本类中A方法(有事务注解)调用其他类中B方法(有事务注解,该类在容器中),B方法中捕获了异常,事务失效不可以回滚,在B方法中的catch里进行异常抛出则可以正常回滚。

本类中A方法(有事务注解)调用其他类中B方法(有事务注解,该类在容器中),A方法中捕获了异常,spring事务机制检测到异常,进行回滚。

所以最好在业务层catch中抛出异常让控制层捕获。

2、spring中事务是代理模式

在该类中A方法调用本类中B方法,A方法上没有事务注解,B方法上有事务注解,则B方法中出现异常,B方法事务不会回滚,A方法没有事务注解也不会回滚。

3、A方法如果有事务注解

调用了本类B方法,B方法出现异常也整体可回滚。

4、本类中A方法调用

其他类中B方法(有事务注解,该类在容器中),B方法发生异常,可以回滚。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • JAVA8如何妙用Optional解决NPE问题详解

    JAVA8如何妙用Optional解决NPE问题详解

    在Java中,null代表一个不存在的对象,如果对它进行操作就会抛出java.lang.NullPointerException异常,下面这篇文章主要给大家介绍了关于JAVA8如何妙用Optional解决NPE问题的相关资料,需要的朋友可以参考下
    2018-06-06
  • SpringBoot项目打成War布署在Tomcat的详细步骤

    SpringBoot项目打成War布署在Tomcat的详细步骤

    这篇文章主要介绍了SpringBoot项目打成War布署在Tomcat,本文分步骤结合图文实例给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • java使用Process调用exe程序及Process.waitFor()死锁问题解决

    java使用Process调用exe程序及Process.waitFor()死锁问题解决

    在编写Java程序时,有时候我们需要调用其他的诸如exe,shell这样的程序或脚本,下面这篇文章主要给大家介绍了关于java使用Process调用exe程序及Process.waitFor()死锁问题解决的相关资料,需要的朋友可以参考下
    2022-12-12
  • 浅谈JVM中的JOL

    浅谈JVM中的JOL

    我们天天都在使用java来new对象,但估计很少有人知道new出来的对象到底长的什么样子?对于普通的java程序员来说,可能从来没有考虑过java中对象的问题,不懂这些也可以写好代码。今天,给大家介绍一款工具JOL,可以满足大家对java对象的所有想象。
    2021-06-06
  • Spring Boot 入门教程

    Spring Boot 入门教程

    相信很多人都接触spring框架很长时间了,每次搭建spring框架的时候都需要配置好多的jar、xml,做很多繁琐重复的配置,稍微不留神就会出现各种各样的问题。今天给大家介绍一下如何利用Spring Boot快速的搭建一个简单的web应用
    2017-03-03
  • Java基础第三篇 构造器与方法重载

    Java基础第三篇 构造器与方法重载

    显式初始化要求我们在写程序时就确定初始值,这有时很不方便。我们可以使用构造器(constructor)来初始化对象。构造器可以初始化数据成员,还可以规定特定的操作。这些操作会在创建对象时自动执行。下面文字将对该内容做详细介绍,需要的小伙伴请参考
    2021-09-09
  • 关于Scanner对象的输入结束标记问题

    关于Scanner对象的输入结束标记问题

    这篇文章主要介绍了关于Scanner对象的输入结束标记问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Spring Boot静态资源路径的配置与修改详解

    Spring Boot静态资源路径的配置与修改详解

    最近在做SpringBoot项目的时候遇到了“白页”问题,通过查资料对SpringBoot访问静态资源做了总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09
  • 从内存方面解释Java中String与StringBuilder的性能差异

    从内存方面解释Java中String与StringBuilder的性能差异

    我们通常会发现使用StringBuffer或StringBuilder创建出来的字符串在拼接时回避String要来得快,尤其是StringBuilder,本文就从内存方面解释Java中String与StringBuilder的性能差异,需要的朋友可以参考下
    2016-05-05
  • spring中JdbcTemplate操作oracle的存储过程实例代码

    spring中JdbcTemplate操作oracle的存储过程实例代码

    JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用,JdbcTemplate是Spring的一部分,下面这篇文章主要给大家介绍了关于spring中JdbcTemplate操作oracle的存储过程的相关资料,需要的朋友可以参考下
    2023-04-04

最新评论