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事务失效场景内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何使用Jenkins构建GIT+Maven项目

    如何使用Jenkins构建GIT+Maven项目

    这篇文章主要介绍了如何使用Jenkins构建GIT+Maven项目,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Java组件javabean用户登录实例详解

    Java组件javabean用户登录实例详解

    这篇文章主要为大家详细介绍了Java组件javabean用户登录实例,内容有用户登录,注册和退出等,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • SpringBoot消息国际化配置实现过程解析

    SpringBoot消息国际化配置实现过程解析

    这篇文章主要介绍了SpringBoot消息国际化配置实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Spring MVC项目中log4J和AOP使用详解

    Spring MVC项目中log4J和AOP使用详解

    项目日志记录是项目开发、运营必不可少的内容,有了它可以对系统有整体的把控,出现任何问题都有踪迹可寻。下面这篇文章主要给大家介绍了关于Spring MVC项目中log4J和AOP使用的相关资料,需要的朋友可以参考下。
    2017-12-12
  • Java 中DateUtils日期工具类的实例详解

    Java 中DateUtils日期工具类的实例详解

    这篇文章主要介绍了Java 中DateUtils日期工具类的实例详解的相关资料,有时候开发java项目使用日期类型,这里介绍下日期工具类,需要的朋友可以参考下
    2017-08-08
  • spring中WebClient如何设置连接超时时间以及读取超时时间

    spring中WebClient如何设置连接超时时间以及读取超时时间

    这篇文章主要给大家介绍了关于spring中WebClient如何设置连接超时时间以及读取超时时间的相关资料,WebClient是Spring框架5.0引入的基于响应式编程模型的HTTP客户端,它提供一种简便的方式来处理HTTP请求和响应,需要的朋友可以参考下
    2024-08-08
  • Java中的循环笔记整理(必看篇)

    Java中的循环笔记整理(必看篇)

    下面小编就为大家带来一篇Java中的循环笔记整理(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Spring Cloud Feign接口返回流的实现

    Spring Cloud Feign接口返回流的实现

    这篇文章主要介绍了Spring Cloud Feign接口返回流的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Java堆&优先级队列示例讲解(下)

    Java堆&优先级队列示例讲解(下)

    这篇文章主要通过示例详细为大家介绍Java中的堆以及优先级队列,文中的示例代码讲解详细,对我们了解java有一定帮助,需要的可以参考一下
    2022-03-03
  • SpringBoot项目如何使用多线程执行定时任务

    SpringBoot项目如何使用多线程执行定时任务

    在SpringBoot项目中使用多线程执行定时任务,可以避免一个耗时任务影响其他任务,通过配置线程池任务调度器,Spring会自动使用多线程执行定时任务
    2025-01-01

最新评论