Spring事务注解@Transactional失效的八种场景分析
作者:初夏0811 发布时间:2022-03-09 13:36:13
首先说一下最近自己遇到的一个坑:
@Transactional
service A(){
try{
insert();
serviceB.update();
}catch(){
throw new RunTimeException();
}
}
serviceB(){
@Transactional
update(){
try{
mapperB.update();
}catch(){
throw new RunTimeException();
}
}
}
mapperB (){
try{
//doSomething....
return true;
}catch(){
return false;
}
}
上面的例子中我的异常出现再//doSomething…的一个sql执行异常了,serviceA 中的insert却一直不能回滚,根本原因在于异常处只返回了false,并没有抛出运行异常,没有往上一层抛,serviceB中有抛出运行异常,却只拿到了一个false,故不会回滚。
下面总结下常见的事务不会回滚的集中情况:
1、数据库引擎不支持事务
这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。
2、没有被 Spring 管理
如下面例子所示:
// @Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
// update order
}
}
如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。
3、方法不是 public 的
@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。
以下来自 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.
也是说的上面那个意思。
4、自身调用问题
来看两个示例:
@Service
public class OrderServiceImpl implements OrderService {
public void update(Order order) {
updateOrder(order);
}
@Transactional
public void updateOrder(Order order) {
// update order
}
}
update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?
再来看下面这个例子:
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void update(Order order) {
updateOrder(order);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateOrder(Order order) {
// update order
}
}
这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?
这两个例子的答案是:不管用!
因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。
5、数据源没有配置事务管理器
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
如上面所示,当前数据源若没有配置事务管理器,那也是白搭!
6、不支持事务
来看下面这个例子:
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void update(Order order) {
updateOrder(order);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void updateOrder(Order order) {
// update order
}
}
Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起,都主动不支持以事务方式运行了,那事务生效也是白搭。
7、异常被吃了
这个也是出现比较多的场景:
// @Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
// update order
} catch {
}
}
}
把异常吃了,然后又不抛出来,事务怎么回滚吧!
8、异常类型错误
上面的例子再抛出一个异常:
// @Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
// update order
} catch {
throw new Exception("更新错误");
}
}
}
这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:
@Transactional(rollbackFor = Exception.class)
这个配置仅限于 Throwable 异常类及其子类。
本文总结了八种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这三个了。
来源:https://blog.csdn.net/m0_37899908/article/details/117093672


猜你喜欢
- 由于项目需要在NDK中使用网络开发,对于c语言网络开发来说,libcurl库是个很不错的选择,但android系统中并没有自带该库,所以就得
- 一:ArrayList和LinkedList的大致区别如下:1.ArrayList是实现了基于动态数组的数据结构,ArrayList实现了长
- 发现问题:之前用springAOP做了个操作日志记录,这次在往其他类上使用的时候,service一直注入失败,找了网上好多内容,发现大家都有
- 好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客:Android UI设计系列之自定义Dialog实现各种风格的对
- 是不是很讨厌mybatis Generator帮我们生成代码的时候在Mapper和mapper.xml文件中生成的一大堆注解?今天在看MyB
- 1. ObsoleteAttributeObsoleteAttribute 适用于除组件、模块、参数和返回值以外的所有程序元素。将元素标记为
- 本文实例讲述了Spring实战之属性占位符配置器用法。分享给大家供大家参考,具体如下:一 配置文件<?xml version=&quo
- 本文实例分析了c#中Empty()和DefalutIfEmpty()用法。分享给大家供大家参考。具体分析如下:在项目中,当我们想获取IEnu
- 第一步:图形验证码接口1.使用第三方的验证码生成工具Kaptchahttps://github.com/penggle/kaptcha@Co
- import android.app.ListActivity; import android.database.Cursor; impor
- 本文实例讲述了Java面向对象程序设计:抽象类,接口用法。分享给大家供大家参考,具体如下:本文内容:抽象类接口抽象类与接口的异同
- DebugLZQ在网上搜索相关文件加密的程序,发现给出的基本都是针对“字符创”、“文本”的加密与解密。对视频文件、图片等一般文件的加密解密程
- 一、spring-boot-devtools在pom中直接引入依赖<dependency> <groupId&
- 本文实现android系统照相机的调用来拍照项目的布局相当简单,只有一个Button:<RelativeLayout xmlns:an
- 首先我们常用的注解包括@Entity、@Table、@Id、@IdClass、@GeneratedValue、@Basic、@Transie
- @Profiles和@PropertySource根据环境切换配置文件使用@PropertySource注解加载配置文件,并制定解析配置文件
- package cn.hackcoder.beautyreader.broadcast;import android.content.Bro
- 本文实例讲述了C#使用round函数四舍五入的方法。分享给大家供大家参考。具体分析如下:C#中的round函数实际上不是真正的四舍五入函数,
- 异步log4j2的location信息打印问题背景:项目改造过程中将log4j2改成异步,发现行号没有打印,于是扒了下官方文档,大概陈述下:
- 本文实例为大家分享了C#汉字转换为拼音缩写的实现代码,供大家参考,具体内容如下using System;using System.Confi