spring事务处理中,同⼀个类中:A⽅法(⽆事务)调B⽅法
(有事务),事务不⽣效问题
1. public class MyEntry implements IBaseService{
2. public String A(String jsonStr) throws Exception{
3. UserInfo user = null;spring是什么意思1
4. UserDetail userDetail = null;
5. UserMsg(user,userDetail ,jsonStr);
6. if(null!= user){
7. this.B(user,userDetail);
8. }
9. return "";
10. }
11. //此处需要事务
12. private String B(UserInfo user, UserDetail detail) throws DBException{
13. baseDao.saveObject(user);
14. baseDao.saveObject(detail);
15. }
16. }
<tx:method name="A" propagation="REQUIRED" />
那么如果baseDao.saveObject(detail)异常,整个B⽅法全部回滚。没问题
但是
如果我在配置事务的时候仅仅对 name="B",并且不对A进⾏配置事务,如下:
<tx:method name="B" propagation="REQUIRED" />
那么如果baseDao.saveObject(detail)异常,⽅法B不能全部回滚(也就是说虽然baseDao.saveObject(detail)没有保存成功,但是baseDao.saveObject(user)保存成功了)
在 spring 中⼀共定义了六种事务传播属性,如下
PROPAGATION_REQUIRED -- ⽀持当前事务,如果当前没有事务,就新建⼀个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- ⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏。
PROPAGATION_MANDATORY -- ⽀持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则进⾏与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的⼀个特殊变量。
它要求事务管理器或者使⽤JDBC 3.0 Savepoint API提供嵌套事务⾏为(如Spring的DataSourceTransactionManager)
研究源码、调试程序得出结论:
A如果没有受事务管理:则线程内的connection 的 autoCommit为true。
B得到事务时事务传播特性依然⽣效,得到的还是A使⽤的connection,但是不会改变autoCommit的属性。
所以B当中是按照每条sql进⾏提交的。
在⼀个Service内部,事务⽅法之间的嵌套调⽤,普通⽅法和事务⽅法之间的嵌套调⽤,都不会开启新的事务.是因为spring采⽤动态动态代理最终都是要调⽤原始对象的,⽽原始对象在去调⽤⽅法时,是不会再触发代理了!
代理机制来实现事务控制,⽽动态代理最终都是要调⽤原始对象的,⽽原始对象在去调⽤⽅法时,是不会再触发代理了!
解决办法:
可以把⽅法B放到另外⼀个service或者dao,然后把这个server或者dao通过@Autowired注⼊到⽅法A的bean⾥⾯,这样即使⽅法A没⽤事务,⽅法B也可以执⾏⾃⼰的事务了。
参考⽂章:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论