遇到Spring事务失效,你该怎么办?

这篇具有很好参考价值的文章主要介绍了遇到Spring事务失效,你该怎么办?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring 事务场景失效是一个常见的问题。今天来分析这个问题。

遇到Spring事务失效,你该怎么办?

1、事务方法被final、static关键字修饰,方法访问权限不是public

@Service
public class UserService {
    
    @Autowired
    private UserDao userDao;

    // final修饰的事务方法
    @Transactional
    public final void addUser(User user) {
        userDao.addUser(user);
    }

    // 访问权限不是public的事务方法
    @Transactional
    protected void updateUser(User user) {
        userDao.updateUser(user);
    }

    // 静态方法的事务方法
    @Transactional
    public static void deleteUser(int userId) {
        userDao.deleteUser(userId);
    }
}

失效原因

  1. 事务方法被final、static关键字修饰:这是因为Spring事务的实现依赖于AOP技术,而final、static方法无法被代理,因此在这些方法中调用事务方法,事务无法生效。
  2. 方法访问权限不是public:Spring事务的实现也是基于AOP的,所以在非public的方法中调用事务方法,无法触发AOP代理,因此事务不会生效。

2、同一个类中,方法内部调用

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    public void addUser(User user) {
        // 事务方法内部调用了updateUser方法,事务失效
        updateUser(user);
    }

    public void updateUser(User user) {
        userDao.updateUser(user);
    }
}

失效原因
在同一个类中,事务方法内部调用其他方法时,可能会导致事务失效。这是因为Spring的事务是基于AOP(面向切面编程)实现的,在同一个类中的方法内部调用其他方法时,实际上是调用的类的内部方法,而不是通过代理调用方法,从而导致事务无法生效。

3、事务注解配置错误

  • 没有开启事务注解扫描或者没有在配置文件中开启事务。
<!-- 开启事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启事务注解扫描 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
  • 没有在需要开启事务的方法上添加@Transactional注解。
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    public void addUser(User user) {
        userDao.addUser(user);
    }
}
  • 在事务方法上添加了错误的propagation或isolation属性值。
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public void transferMoney(String fromAccount, String toAccount, double amount) {
    // transfer money from one account to another
}

  • 在注解中配置了错误的rollbackFor或noRollbackFor属性值。
@Transactional(rollbackFor = RuntimeException.class, noRollbackFor = BusinessException.class)
public void updateUserInfo(User user) throws BusinessException {
    // update user information
}

4、 事务注解被覆盖导致事务失效

@Transactional(propagation = Propagation.REQUIRED)
public class ParentClass {
    public void doSomething() {
        // ...
    }
}

public class ChildClass extends ParentClass {
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void doSomething() {
        // ...
    }
}

在上述代码中,ParentClass 中的事务注解 @Transactional(propagation = Propagation.REQUIRED) 覆盖了 ChildClass 中的事务注解 @Transactional(propagation = Propagation.NOT_SUPPORTED),因此当调用 ChildClass 中的 doSomething 方法时,事务将会失效。为了解决这个问题,可以在子类中将事务注解的属性值与父类保持一致。

5、 嵌套事务和异常被捕获导致事务失效

嵌套事务是指在一个事务内部,开启了一个新的事务,这个新事务与外部事务是嵌套关系,也就是内部事务依赖于外部事务,只有外部事务提交成功,内部事务才能生效。

在 Spring 中,通过设置事务传播级别来实现嵌套事务,常见的传播级别包括:

  • REQUIRED:如果当前存在事务,则加入该事务;否则,创建一个新的事务。这是默认值。
  • REQUIRES_NEW:每次都创建一个新的事务,并将当前事务挂起。
  • NESTED:如果当前存在事务,则在嵌套事务内执行;否则,创建一个新的事务。这种方式也是嵌套事务的实现方式。
    在嵌套事务中,如果外部事务回滚了,那么内部事务也会回滚;如果内部事务回滚了,只会回滚内部事务,而不会影响到外部事务。

然而,使用嵌套事务需要注意一些坑:

  1. 数据库支持
    嵌套事务是由数据库来实现的,不同的数据库对于嵌套事务的支持不同,有些数据库甚至不支持嵌套事务,例如 MySQL 默认是不支持嵌套事务的。

  2. 事务管理器
    Spring 事务是通过事务管理器来实现的,不同的事务管理器对于嵌套事务的支持也不同,如果使用的事务管理器不支持嵌套事务,那么嵌套事务就会失效。

  3. 异常处理
    在嵌套事务中,如果内部事务抛出了异常,并且外部事务没有捕获这个异常,那么整个事务会回滚,包括内部事务和外部事务。因此,在嵌套事务中,要注意异常处理。

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(propagation = Propagation.REQUIRED)
    public void updateUser(User user) {
        jdbcTemplate.update("update user set name = ? where id = ?", user.getName(), user.getId());
        try {
            insertLog(user.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Transactional(propagation = Propagation.NESTED)
    public void insertLog(Long userId) {
        jdbcTemplate.update("insert into log(user_id) values(?)", userId);
        throw new RuntimeException("插入日志失败");
    }

}

上述代码中,updateUser 方法中调用了 insertLog 方法,insertLog 方法使用了 Propagation.NESTED 的传播级别来实现嵌套事务。当插入日志时,会抛出 RuntimeException 异常,并被 updateUser 方法中的 try-catch 块捕获。在这种情况下,虽然 insertLog 方法的事务会回滚,但是由于使用的是嵌套事务,所以 updateUser 方法的事务并不会回滚,导致了事务失效。文章来源地址https://www.toymoban.com/news/detail-414075.html

到了这里,关于遇到Spring事务失效,你该怎么办?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 遇到移动号码手机停机怎么办?如何自助解决上网问题?

    今天是 2022年4月1日,是的,愚人节。 一大早去赶地铁上班(深圳高峰期挤地铁特别是 1 号线简直被挤爆)的路上,发现上不了网了!原来是话费停机欠费了,忘了提前充话费。想回家连个 WiFi 但是出门很远了,还是算了。 后来我想:要不要随便去一家门店蹭个 WiFi?毕竟早

    2024年02月16日
    浏览(71)
  • 阿里云haas100遇到hidapi.h错误怎么办?

    摘要:使用vscode拉取ucloud_ai_demo例程后,会出现缺少hidapi.h的错误。原因不明,但是进行简单的修改,就可以正常编译通过了,详见正文。 例程的位置是 ucloud_ai_demo: ucloud ai demo code https://gitee.com/alios-things/ucloud_ai_demo ucloud_ai_demo是基于云端AI能力实现的AI识别案例,主要有三个部

    2024年02月01日
    浏览(46)
  • 单片机遇到“auto segment too large“怎么办

    遇到这个情况有可能是某一个数组太大,然后单片机内部数据存储区不够用, 所以可以把这个数据存在单片机外例如      int led[8][8]={         {1,1,1,1,1,1,1,1},//1         {1,0,0,0,0,0,0,1},//2         {1,0,0,0,0,0,0,1},//3         {1,0,0,0,0,0,0,1},//4         {1,0,0,0,0,0,0,1},//5  

    2024年02月14日
    浏览(56)
  • 在VSCODE编辑器是用ctrl+c和ctrl+s(复制粘贴)失效怎么办

    有时我们在开发过程中,由于使用vsccode太长时间导致复制ctrl+c和ctrl+s会失效,之前我的处理方式是重启浏览器,但有时候这样太耗时间了,但发现一个方法可以解决,就是刷新下编辑器的timeline就行,如下图:

    2024年02月15日
    浏览(53)
  • Stripe轮询系统收单遇到条纹Block(拦截)怎么办

            今年上半年不少小伙伴用条纹收款用得可谓不亦乐乎,国内行情一片沸腾,条纹支付成功率几乎100%,出款率也是80~90%。六月底风云突变,条纹风控大升,成功率10~20%,即使客户购意愿很强,连续支付,付款是成功了,但条纹的雷达提醒高风险。这种情况下,条纹账号

    2024年02月12日
    浏览(46)
  • vscode gitlens失效,怎么办This GitLens pre-release version has expired.

    gitlens 可以很方便看具体哪一行代码的提交修改记录,很方便。 但是这个插件总是会过期,This GitLens pre-release version has expired.就是总要升级到最新版本才能使用。 前提:内网环境,每次都要下载 vsix 离线文件下来安装。 gitlens总是会过期,需要经常去下载(vscode market直接下载

    2024年02月07日
    浏览(53)
  • 遇到“EXE不是有效Win32应用程序”的错误提示,怎么办

    遇到 “EXE 不是有效 Win32 应用程序 ” 的错误提示,有时即使双击运行任意一个 EXE 格式的 可执行文件 ,同样会出现错误问题,问题现象如下所示: 解决方法: 1 、查杀病毒并删除 注册表 信息 先进入 安全模式 ,运行系统中已安装好的杀毒软件,来对系统执行一次全盘杀毒

    2024年02月04日
    浏览(75)
  • Google谷歌gmail邮箱账号注册遇到:此电话号码无法用于进行验证怎么办?

    申请注册Google谷歌gmail邮箱账号,验证您的手机号码时遇到:此电话号码无法用于进行验证怎么办?因为遇到此电话号码无法用于进行验证问题,将无法继续完成谷歌gmail邮箱google账号注册。 【解决办法】 您可以按下面的教程尝试注册解决,如已尝试仍无法解决注册Google谷歌

    2023年04月17日
    浏览(59)
  • 应届毕业生找Python工作遇到的难题,刚毕业没有工作经验该怎么办?

    如果你是一名应届生,你可以通过其他方式来证明自己的能力。以下是一些建议: 在校期间积累项目经验。如果你在学校里有过Python项目经验,可以在简历中详细描述你的项目经历和成果。这可以帮助雇主了解你的技能和能力。 参加编程比赛。参加编程比赛可以展示你的编

    2024年02月02日
    浏览(50)
  • 阿里云物联网APP编程时遇到com.aliyun.teaopenapi错误怎么办?

    摘要:本文介绍编写阿里云物联网APP安卓程序遇到com.aliyun.teaopapi无法Import错误的解决方法。 本文编程环境是:    调用openapi的时候,需要导入一些在线的库。这些库大多包含“tea”这个单词。 为什么阿里云的api用tea做代号,尚不可知,但是导入的时候,肯定是需要按照阿里

    2023年04月14日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包