zoukankan      html  css  js  c++  java
  • spring 事务处理中,同一个类中:A方法(无事务)调B方法(有事务),事务不生效问题

    1. public class MyEntry implements IBaseService{
    2. public String A(String jsonStr) throws Exception{
    3. UserInfo user = null;
    4. UserDetail userDetail = null;
    5. this.getUserMsg(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也可以执行自己的事务了。

    参考文章:

    https://www.jianshu.com/p/0da29e4f354a

    http://blog.csdn.net/dapinxiaohuo/article/details/52092447

    http://www.iteye.com/topic/35907/

  • 相关阅读:
    Linux同一机器设置多个IP2019-7-6
    使用Apache服务部署静态网站2019-7-5
    系统状态检测命令2019-7-5
    简单的shell脚本
    常用的系统工作命令2019-7-4
    Lnmp架构部署动态网站环境.2019-7-3-1.4
    Lnmp架构部署动态网站环境.2019-7-3-1.3
    Linux安装ftp服务-详细步骤
    循环删除List集合的元素
    反射-父类获取子类属性并赋值
  • 原文地址:https://www.cnblogs.com/edda/p/13614025.html
Copyright © 2011-2022 走看看