在同一个类中,一个方法调用另外一个有注解(比如@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()方法也没有运行。

了解了失效的原因,解决的方法就简单了(两种):
把这两个方法分开到不同的类中;
把注解加到类名上面;

参考:
http://stackoverflow.com/questions/18590170/transactional-does-not-work-on-method-level

---------------------
作者:Clement-Xu
来源:CSDN
原文:https://blog.csdn.net/clementad/article/details/47339519

@Transational)的方法,注解失效的原因和解决方法的更多相关文章

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

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

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

    参考 原文链接 @Transactional does not work on method level 描述 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational) ...

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

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

  4. vue父组件引用子组件方法显示undefined问题原因及解决方法

    关于vue父组件引用子组件问题 1.首先导入子组件并且在components中定义子组件 2.引用子组件,并定义ref,ref定义的名称用于 this.$refs所调用的名称 3.调用子组件的方法 ( ...

  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. oracle 索引失效原因及解决方法

    oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 ‍1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...

  8. coreseek常见错误原因及解决方法

    coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...

  9. Java读带有BOM的UTF-8文件乱码原因及解决方法

    原因: 关于utf-8编码的txt文件,windows以记事本方式保存时会在第一行最开始处自动加入bom格式的相关信息,大概三个字节! 所以java在读取此类文件时第一行时会多出三个不相关的字节,这样 ...

随机推荐

  1. openwrt多wan限上下行速脚本,基于qosv4,imq模块替换成ifb模块[ZT]

    转自: http://www.right.com.cn/forum/thread-169414-1-1.html ,本人未经测试,转来自已备用 由于树莓派2装openwrt官方没有imq模块, 好像说 ...

  2. IE9及以下版本获取上传文件的大小

    IE9及以下版本不能识别files属性:获取图片需要设置浏览器 打开IE_工具_internet选项_安全_自定义级别. 启用ActiveX,开启跨域: var fso=new ActiveXobje ...

  3. tap news:week5 0.0 create react app

    参考https://blog.csdn.net/qtfying/article/details/78665664 先创建文件夹 安装create react app 这个脚手架(facebook官方提 ...

  4. 使用__all__限制模块可被导入对象

    经常我们会编写自定义模块,用于被别的脚本调用;有时候为了方便,会使用from module_name import *的方式导入,这样会把模块中全部对象导入进来; 使用__all__结合列表,可以控制 ...

  5. C# 监测每个方法的执行次数和占用时间(测试1)

    在Nuget引用 Castle.DynamicProxy 和 Newtonsoft.Json 这个 原文:http://www.cnblogs.com/RicCC/archive/2010/03/15 ...

  6. 学JS的心路历程 -数组常见处理方法

    昨天我们有提到说for-of和forEach可以用来处理数组,但其实还有很多方法可以更快速及精简代码的达到你要的效果. 话不多说,我们赶紧来看吧! Array.prototype.map() 会回传一 ...

  7. js 浏览器页面切换事件

    document.addEventListener('visibilitychange', function() { console.log(isHidden() + "-" + ...

  8. Java用户输入数值,做简单的猜数字游戏,导入基础的工具包util

    Java用户输入数值,做简单的猜数字游戏,导入基础的工具包util,导入包的方法为,import java.util.*: 完整的实例代码: /* 导入基础工具包 */ import java.uti ...

  9. Gimbal Lock

    [Gimbal Lock] 万向锁源于欧拉角的是有序处理的.U3D中的序列为: y->x->z.当旋转y时,local坐标系与世界坐标系重合,所以y等于永远按惯性坐标旋转.当x旋转+/-9 ...

  10. java和c#中String

    java中: c#中: 1.拼接字符串 sql语句中 in() str="'001','002','003'";至于产生string就这样  str1="'001'&qu ...