请教各位大佬一个关于事务的问题:
1、 method_A(T1事务)中查询了某条记录A(A.name = 1);然后调用method_B(T2事务,并且是REQUIRES_NEW )
2、在 method_B中修改了记录A并提交保存(A.name = 2);(method_B方法结束)
3、然后回到 method_A 中再次查询这条记录A,发现得到的A.name = 1;但是此时数据库中的A.name = 2 。
本来我是在hibernate中遇到的,然后就重新去理解了下REQUIRES_NEW 。然后我用mybatis也测试了,得到的也上面个结论。
但是,我用spring的JdbcTemplate测试却发现: 本来在(3)得到A.name=1,但实际A.name =2.但hibernate、mybatis得到的都是A.name=1。
想问的是: 为什么JdbcTemplate得到的结果会和hibernate/mybatis不一样? 难道是因为hibernate/mybatis缓存的原因吗? 但解释不了REQUIRES_NEW的特性啊?
示例代码
newCityService中的方法全部是 REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRED) public void error(){ long id = 1 ; City c1 = cityDao.selectCityById(id); System.out.println("init select: " + c1); City c2 = newCityService.newUpdate(c1); System.out.println("new update: " +c2); City c3 = cityDao.selectCityById(id); System.out.println("cur select: " + c3); City c4 = newCityService.newSelect(id); System.out.println("new select: " + c4); System.out.println("---------------------------"); }
首先我不得不说你问题描述的很不清楚,其次你在一个事务管理起来里面更改查询结果当然不会变。首先你要明白事务管理是干嘛的,所有的方法都能执行并且没有异常事务管理才会提交到数据库,值才会发生改变。你在c2里面更改但是还没有提交到数据库所以查询到的值还是1,还有不要在一个事务管理器调用另一个带有事务管理的方法。JdbcTemplate是没有二级缓存的,hibernate是有的,myBatis没有用过不知道。
c2事务肯定是提交的了。 在c2断点后,去数据库查询就是修改后的值。因为c2的update是用的REQUIRES_NEW。
hibernate/mybatis在c3得到的是未修改的值,但jdbctemplate得到的就是数据库现在的值.
(语文学的不好,2333)
@淡丶无欲: 所以你在c2单独开启了一个事物管理?
@时光城主: 恩啊。 但现在疑惑的时,JdbcTemplate得到的与 hibernate/mybatis的不一致。发现又没理解到 REQUIRES_NEW
@淡丶无欲: JdbcTemplate是一个轻量级的jdbc,对数据库处理都是直接做出反应的。不论你添加修改删除只要执行了数据库值就会改变,但是hibernate不是,hibernate提供了二级缓存。如果你在C2单独开启了事物那么这个问题就清楚了,一个事物管理不到另一个事物。如果你在C2没有开启那么你更改的值就不会提交到数据库直到这个事物执行完毕才会提交,但是你单独开启了事物所以在执行c2的时候值已经提交到数据库了但是这个事物管理里面不知道C2已经提交了所以才会查询到的值和数据库不一致。
@时光城主: 我个人能想到的可能是因为缓存。但是, REQUIRES_NEW的特性"将当前事务挂起,新起一个新的事务。" 但新事务执行完后,回到当前事务,当前事务中得到的应该是当前事务的值。(如以上的hibernaye/mybatis得到的结果)。 但JdbcTemplate也在事务管理内吧,它得到的确实最新数据库的。
感谢回答,我可能需要再看看
@淡丶无欲: 我也是无语了,你这个事务管理应该是hibernate的事务你怎么管理到JdbcTemplate,JdbcTemplate和当前事务一点关系都没有因为管理不到它,只有基于hibernate的新增和修改、查询事务才能管理到。事务管理也是建立在一个基础上面,不是所有的都能管理。
应该是特性你理解错了吧