使用@Transactional应注意的问题

@Transactional 基本原理概述

在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据@Transactional 的属性配置信息,这个代理对象决定该声明@Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务。

你需要注意的事

  1. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能
  2. Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。
  3. 当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,还是在具体的类上使用 @Transactional 注解比较好。
  4. 避免 Spring 的 AOP 的自调用问题:自调用就是方法A内调用本类的另一个加上事务注解的方法B时,方法B中对数据库的操作是不带事务的。

Spring AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚。

失效原因

方法one方法two都是public的:

  • classA中 ,任意要调用classB的方法,是通过spring代理的方式,那么spring的注解才会生效
  • classA中,方法one 调用同class内的方法two,即this调用,spring注解不会生效(例如@Cachable,@Transaction)

解决方法

既然已知原因,那么解决的方法就有了,核心思想就是如何获得动态代理对象,而不是使用this去调用。

方案一:使用AspectJ代理

@Service
public class OrderService {private void insert() {insertOrder();}
@Transactionalpublic void insertOrder() {//insert log info//insertOrder//updateAccount}
}

insertOrder 尽管有@Transactional 注解,但它被内部方法 insert 调用,事务被忽略,出现异常事务不会发生回滚。

上面的两个问题@Transactional 注解只应用到 public 方法和自调用问题,是由于使用 Spring AOP 代理造成的。为解决这两个问题,可以使用 AspectJ取代 Spring AOP 代理,但现在有更好的解决方法。

方案二:利用AopContext.currentProxy()方法获得代理

方法的意思是尝试返回当前AOP代理。这种做法非常简洁,但是在默认情况下是不起作用的!因为AopContext中拿不到currentProxy,会报空指针。需要一些额外的配置,但不能对所有的注解拦截都有效,这是因为这些注解不是用的AspectJ代理,如果是@Transactional事务注解的话, 则是生效的,具体细节要翻源码了,这里不推荐使用。

方案三:通过ApplicationContext来获得动态代理对象(推荐)

@Component
public class AsyncService implements ApplicationContextAware {private ApplicationContext applicationContext;public void async1() {System.out.println("1:" + Thread.currentThread().getName());// 使用AppicationContext来获得动态代理的bean,然后再执行你调用的方法this.applicationContext.getBean(AsyncService.class).async2();}@Asyncpublic void async2() {System.out.println("2:" + Thread.currentThread().getName());}// 注入ApplicationContext@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}

转载于:https://www.cnblogs.com/keeya/p/11180612.html

使用@Transactional应注意的问题相关推荐

  1. 写出漂亮代码的45个小技巧

    不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是没有人可以问,此时只能心里默默地问候这个留坑的兄弟. ...

  2. 写出漂亮代码的45个小技巧,真好用

    大家好,我是三友~~ 不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是没有人可以问,此时只能心里默默 ...

  3. 这45个小技巧,帮你写出一手同事都羡慕的漂亮代码!

    这45个小技巧,帮你写出一手同事都羡慕的漂亮代码! 不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是 ...

  4. 使用这45个小技巧,帮助你写出更优雅的代码

    前言 不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是没有人可以问,此时只能心里默默地问候这个留坑的 ...

  5. Spring_Spring@Transactional

    Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...

  6. Spring @Transactional (一)

    Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...

  7. @Transactional事务的使用和注意事项及其属性

    事务管理 提示 @Transactional注解只能应用到public可见度的方法上,可以被应用于接口定义和接口方法,方法会覆盖类上面声明的事务. 示例: 例如用户新增需要插入用户表.用户与岗位关联表 ...

  8. SSM框架中使用Spring的@Transactional注解进行事务管理

    一 介绍 在企业级应用中,保护数据的完整性是非常重要的一件事.因此不管应用的性能是多么的高.界面是多么的好看,如果在转账的过程中出现了意外导致用户的账号金额发生错误,那么这样的应用程序也是不可接受的 ...

  9. Spring @Transactional实际如何工作?

    在本文中,我们将深入探讨Spring事务管理. 我们将讨论@Transactional在@Transactional如何真正工作. 其他即将发布的帖子将包括: 如何使用传播和隔离等功能 主要陷阱是什么 ...

最新文章

  1. 安卓项目查手机电量功能_不做低头族,一键开启手机上的这一功能,手机信息随时查...
  2. Python 之vim编写python自动补全
  3. Eclipse 启动问题:'Initilizing Java Tooling' has encountered a problem(。。。)
  4. 基于Android NDK的交叉编译
  5. vue商城源码_一个标星 5.2k+ 的牛逼开源商城系统
  6. 任务管理器在右下角的图标不显示
  7. [react] 请说说react中Portal是什么?
  8. 运维自动化之使用PHP+MYSQL+SHELL打造私有监控系统(七)
  9. 【原创】纯CSS 仿U9论坛 箭形导航栏 兼容IE6+IE7+FF
  10. Kotlin 文档入门-函数 集合
  11. 最全的PHP后台管理系统源码
  12. anaconda版本选择_Anaconda简介
  13. Vue中数组的响应式操作
  14. 【模式串匹配】Aho-Corasick algorithm - AC字符串匹配算法实现与测试【Python】
  15. 转载: WebKit介绍及总结(一)
  16. 《微信小程序案例12》图片识别功能
  17. kafka是什么?主要用在什么场景
  18. Asciinema终端SSH录屏神器使用
  19. 土是独体字结构吗_发是独体字结构吗
  20. Neural-Motifs 源码解读(3):RelModel类

热门文章

  1. iOS程序员眼中的客户端免登陆(数据迁移已更新)
  2. 网络埋藏了怎样的物联网智慧?
  3. linux安装redis服务,配置PHP扩展
  4. Hadoop 2.X 从入门到精通系列视频课程套餐
  5. 查看Linux服务器网卡流量小脚本shell和Python各一例
  6. iOS系类教程之用instruments来检验你的app
  7. SQL小技巧系列 --- 行转列合并
  8. Node.js做的代理转发服务器
  9. CSS_伪元素_伪类
  10. [CSS]复选框单选框与文字对齐问题的研究与解决.