Spring事务失效场景的详细整理

 更新时间:2022年02月15日 10:14:08   作者:战鹰影视TV  
Spring 事务的传播特性说的是,当多个事务同时存在的时候,Spring 如何处理这些事务的特性,下面这篇文章主要给大家介绍了关于Spring事务失效场景的相关资料,需要的朋友可以参考下

前言

项目中用Spring的 @Transactional 注解控制事务,使用中时常出现事物不生效的场景,本文仅限于日常项目开发中的点滴整理总结,总结以下几点,以备后续参考排查;可能不全,列举出来希望可以帮助有需要的同学,避免踩坑。

数据库引擎不支持事物

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

根据 MySQL 的官方文档:

https://dev.mysql.com/doc/refman/5.5/en/storage-engine-setting.html

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务是硬伤。

没有被 Spring 管理

// @Service (此注解不能去掉)
public class AccountServiceImpl implements AccountService {
@Transactional
public void inser(Account account) {
// insert account
}
}

如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。

方法不是 public 的

以下来自于Spring 官方文档:

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以考虑开启 AspectJ 代理模式。

自身调用问题

看下面代码

@Service
public class AccountServiceImpl implements AccountService {
public void insert(Account account) {
insertAccount(account);
}
@Transactional
public void insertAccount(Account account) {
// insert account
}
}

insert方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 insertAccount 方法,insertAccount 方法上的事务其实是不管用的。

再看下面的代码

@Service
public class AccountServiceImpl implements AccountService {
@Transactional
public void insert(Account account) {
insertAccount(account);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertAccount(Account account) {
// insert account
}
}

这次在 insert 方法上加了 @Transactional,insertAccount 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?

这两个例子的答案是:不管用!

因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。

数据源没有配置事物管理器

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) 
{
return new DataSourceTransactionManager(dataSource);
}

如上面所示,当前数据源若没有配置事务管理器,照样会失效!

不支持事物

@Service
public class AccountServiceImpl implements AccountService {
@Transactional
public void insert(Account account) {
insertAccount(account);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void insertAccount(Account account) {
// insert account
}
}

Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起,详细的可以参考InnoDB的事务隔离级别和传播机制。

都主动不支持以事务方式运行了,那事务生效也是白搭!

异常被吃掉

这个是比较常见的场景

@Service (此注解不能去掉)
public class AccountServiceImpl implements AccountService {
@Transactional
public void inser(Account account) {
try {
// insert account
} catch {
}
}
}

把异常吃了,然后又不抛出来,事务就无法回滚!

异常类型错误

@Service (此注解不能去掉)
public class AccountServiceImpl implements AccountService {
@Transactional
public void inser(Account account) {
try {
// insert account
} catch {
throw new Exception("新增错误");
}
}
}

这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:

@Transactional(rollbackFor = Exception.class)

这个配置仅限于 Throwable 异常类及其子类。

查阅资料,其他失效的场景需注意:1) 像文件导入数据库,用多线程控制;可参考查询spring 多线程事务的问题 2)SpringBoot+Shiro引起事务失效

总结

本文总结了几种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这三个了;像文章开头说的那样,本文不一定总结得全,只是根据经验总结常见的事务失效的场景。

到此这篇关于Spring事务失效场景的文章就介绍到这了,更多相关Spring事务失效场景内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中替代equals,compareTo和toString的方法

    Java中替代equals,compareTo和toString的方法

    这篇文章主要介绍了Java中替代equals,compareTo和toString的方法,文中代码十分详细,帮助大家更好的理解的学习,感兴趣的朋友可以了解下
    2020-06-06
  • MyBatis-Plus自定义通用的方法实现

    MyBatis-Plus自定义通用的方法实现

    MP自带的条件构造器虽然很强大,有时候也避免不了写稍微复杂一点业务的sql,本文主要介绍了MyBatis-Plus自定义通用的方法实现,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Mybatis-Plus处理Mysql Json类型字段的详细教程

    Mybatis-Plus处理Mysql Json类型字段的详细教程

    这篇文章主要给大家介绍了关于Mybatis-Plus处理Mysql Json类型字段的详细教程,Mybatis-Plus可以很方便地处理JSON字段,在实体类中可以使用@JSONField注解来标记JSON字段,同时在mapper.xml中使用json函数来操作JSON字段,需要的朋友可以参考下
    2024-01-01
  • 如何通过properties文件配置web.xml中的参数

    如何通过properties文件配置web.xml中的参数

    这篇文章主要介绍了如何通过properties文件配置web.xml中的参数方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 解析Java和Eclipse中加载本地库(.dll文件)的详细说明

    解析Java和Eclipse中加载本地库(.dll文件)的详细说明

    本篇文章是对Java和Eclipse中加载本地库(.dll文件)进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • SpringBoot实现自定义配置文件提示的方法

    SpringBoot实现自定义配置文件提示的方法

    这篇文章主要介绍了SpringBoot实现自定义配置文件提示的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • C# log4net使用案例详解

    C# log4net使用案例详解

    这篇文章主要介绍了C# log4net使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • springboot自动重连Redis的实现方法

    springboot自动重连Redis的实现方法

    由于网络或服务器问题,Redis连接可能会断开,导致应用程序无法继续正常工作,本文主要介绍了springboot自动重连Redis的实现方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • SpringAop实现原理及代理模式详解

    SpringAop实现原理及代理模式详解

    Spring的AOP就是通过动态代理实现的,使用了两个动态代理,分别是JDK的动态代理和CGLIB动态代理,本文重点给大家介绍下SpringAop实现原理及代理模式,感兴趣的朋友一起看看吧
    2022-04-04
  • SpringMVC MVC架构与Servlet使用详解

    SpringMVC MVC架构与Servlet使用详解

    MVC设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。其中,View 的定义比较清晰,就是用户界面
    2022-10-10

最新评论