参考

原文链接

@Transactional does not work on method level


描述

在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解是不会生效的。

比如,下面代码例子中,有两方法,一个有@Transational注解,一个没有。

  • 如果调用了有注解的addPerson()方法,会启动一个Transaction;
  • 如果调用updatePersonByPhoneNo(),因为它内部调用了有注解的addPerson(),如果你以为系统也会为它启动一个Transaction,那就错了,实际上是没有的。
@Service
public class PersonServiceImpl implements PersonService { @Autowired
PersonDao personDao; @Override
@Transactional
public boolean addPerson(Person person) {
boolean result = personDao.insertPerson(person)>0 ? true : false;
return result;
} @Override
//@Transactional
public boolean updatePersonByPhoneNo(Person person) {
boolean result = personDao.updatePersonByPhoneNo(person)>0 ? true : false;
addPerson(person); //测试同一个类中@Transactional是否起作用
return result;
}
}

如何查看是否启动了Transaction?

设置log leve为debug,可以查看是否有下面这个log,判断是否启动了Transaction:

DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name...

同样地,@Async等其他注解也有这样的问题。

(关于@Async的用法,请参考:http://blog.csdn.net/clementad/article/details/47403185)

原因

spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。

此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。

然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。

为什么一个方法a()调用同一个类中另外一个方法b()的时候,b()不是通过代理类来调用的呢?可以看下面的例子(为了简化,用伪代码表示):

@Service
class A{
@Transactinal
method b(){...} method a(){ //标记1
b();
}
} //Spring扫描注解后,创建了另外一个代理类,并为有注解的方法插入一个startTransaction()方法:
class proxy$A{
A objectA = new A();
method b(){ //标记2
startTransaction();
objectA.b();
} method a(){ //标记3
objectA.a(); //由于a()没有注解,所以不会启动transaction,而是直接调用A的实例的a()方法
}
}

当我们调用A的bean的a()方法的时候,也是被proxy$A拦截,执行proxy$A.a()(标记3),然而,由以上代码可知,这时候它调用的是objectA.a(),也就是由原来的bean来调用a()方法了,所以代码跑到了“标记1”。由此可见,“标记2”并没有被执行到,所以startTransaction()方法也没有运行。

解决方法

了解了失效的原因,解决的方法就简单了(两种):

  1. 把这两个方法分开到不同的类中;
  2. 把注解加到类名上面;

【转】在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法的更多相关文章

  1. 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法

    参考原贴地址:https://blog.csdn.net/clementad/article/details/47339519 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Trans ...

  2. @Transational)的方法,注解失效的原因和解决方法

    在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解是不会生效的. 比如,下面代码例子中,有两方法,一个有@Transational注解,一个没有.如果 ...

  3. 关于用jQuery的animate方法实现的动画在IE中失效的原因以及解决方法

    这几天在学jQuery,本身还只是一个新手,写了一个简单的动画--圆形头像的缩放.本身是用Firefox进行调试的,一切进行的很顺利,缩放可以按照预期执行,结果拿到IE上去之后,发现缩放动画失效了.后 ...

  4. td中不包含汉字的字符串不换行,包含汉字的能换行的问题原因及解决方法

    今天项目中遇到一个问题,一长串的字符串如:003403FF0014E54016030CC655BC3242,但是如:中国河北省石家庄市裕华区槐安路雅清街交口 这样的就可以换行. 原因是:英文字母之间如 ...

  5. js放到head中失效的原因与解决方法

    1.今天写js碰到一个奇怪的问题,写好的js放到body里面执行,但是放到head中没有任何效果,为什么导致这种原因呢? 看失效代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  6. vue+element ui中select组件选择失效问题原因与解决方法

    codejing 2020-07-10 09:13:31  652  收藏 分类专栏: Web Vue Element UI 版权 .当表单form赋完值后,如果后续又对form中某一属性值进行操作如 ...

  7. SpringCache @Cacheable 在同一个类中调用方法,导致缓存不生效的问题及解决办法

    由于项目需要使用SpringCache来做一点缓存,但自己之前没有使用过(其实是没有听过)SpringCache,于是,必须先学习之. 在网上找到一篇文章,比较好,就先学习了,地址是: https:/ ...

  8. Spring @Cacheable注解 && 事务@Transactional 在同一个类中的方法调用不生效

    @Cacheable 注解在对象内部调用不会生效 代码示例:ProductServiceImpl.java public List<ProductInfoVO> getProductLis ...

  9. @Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题

    https://blog.csdn.net/u010235716/article/details/90171802 1. 事务的4种特性       序号 参数 含义1 原子性(Atomicity) ...

随机推荐

  1. python---map 用法 [转载]

    map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 1.当seq只 ...

  2. 炫龙笔记本的gtx965m显卡玩游戏很卡

    这是我遇到的问题,我2016年10月份这样买了一款笔记本,主要看的是性价比吧!神舟.炫龙都是性价比,所以买了炫龙笔记本 配置如下 cpu:i7 4870hq 显卡:gtx965m 内存条:16G 固态 ...

  3. webpack中hash、chunkhash、contenthash区别

    webpack中对于输出文件名可以有三种hash值: 1. hash 2. chunkhash 3. contenthash 这三者有什么区别呢? hash 如果都使用hash的话,因为这是工程级别的 ...

  4. C++中的抽象类

    一.抽象类学习笔记 1.virtual修饰函数(虚函数)后面加=0就称为一个纯虚函数,一个类中只要有纯虚函数那么它就是一个抽象类.抽象类不能用来实例化对象,是用来给他的派生类定义好这些框架的,给使用这 ...

  5. 诡异的磁盘空间100%报警分析得出df -h与du -sh的根本性差别

    前言:早晨磁盘报警刚清空完tomcat和nginx日志,使用的命令是类似echo "" > show_web-error.log或者> show_web-debug.l ...

  6. day 54 JS 之 jquery

    jQuery入门 2017-07-10 jQuery快速入门. jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Doc ...

  7. Singer 学习六 运行&&开发taps、targets (一 taps 运行说明)

    文章内容来来自官方github 说明: singer大部分的taps && targets 是用python编写的,所以内容里面的代码也是使用python 编写 使用python运行s ...

  8. 来自工厂的 PCB 封装建议

    来自工厂的 PCB 封装建议 以前一直没有注意,现在终于知道了,PCB 的封装方向角度是不可以乱摆的,要根据实际编带情况画. 以实物的编带为参考确定 PCB 封装的画法. 而且编带都有标准. 强烈建议 ...

  9. mybatis 一对多,(多对一,一对一

    多对一,和一对一是同一种写法,每种写法又分在数据库关联和在mybatis关联 1,多对一,一对一数据库关联 2,多对一,一对一mybatis关联 3,一对多,数据库关联,注意,Java type改of ...

  10. linux 安装多个版本JDK,指定tomcat的jdk版本

    JDK的下载可以直接到官网下载,这里不再介绍 一.安装JDK 7 vi /etc/profile #set java environmentexport JAVA_HOME=/usr/java/jdk ...