zoukankan      html  css  js  c++  java
  • Spring事务管理中@Transactional

    最近写的一个消息推送的接口,供订单生成后调用,发现每次传过来的时候订单id是存在的,可是利用订单id去查订单信息做后续操作时发现查不到数据,最终发现是订单生成时候业务处理写在service层,加了Spring的事务处理的相关参数:

    @Transactional(value="txManager",isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor={Exception.class})

    而紧接着消息推送的接口里也同样加了Spring的事务处理,导致上一事务未结束得不到返回的数据,这里小结下Spring的事务处理:

    当一个业务活动跨越多个事务,每个事务的传播级别配置不一样。对于这个个问题,涉及到事务的传播级别,定义如下:

    PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务。这是最常见的选择。 
    PROPAGATION_SUPPORTS-- 如果当前没有事务,就以非事务方式执行。 
    PROPAGATION_MANDATORY-- 如果当前没有事务,就抛出异常。 
    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
    PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 
     
    简要代码示例如下:
    复制代码
    /**
    * 营销活动生成订单 A
    *
    *
    @param recvVo
    *
    @return
    *
    @author xingle
    * @data 2014-6-9 下午5:39:10
    */
    @Override
    @Transactional(value
    ="txManager",isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor={Exception.class})
    public synchronized CreatOrderByActyRetnVo creatOrder(BigDecimal userId,
    CreatOrderByActyRecvVo recvVo) {

        </span><span style="color: #008000;">//</span><span style="color: #008000;"> 主订单id</span></br>
        BigDecimal order_id =<span style="color: #000000;"> orderDao.getOrderId();</br>
        OrderInfoVo orderInfoVo </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> OrderInfoVo();</br>
        List</span>&lt;OrderDetailVo&gt; orderDetailLs = <span style="color: #0000ff;">new</span> ArrayList&lt;OrderDetailVo&gt;<span style="color: #000000;">();</br>
        </span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
         * 中间业务处理省略</br>
         </span><span style="color: #008000;">*/</span></br>
        <span style="color: #0000ff;">int</span> m =<span style="color: #000000;"> purchaseDao.createOrderInfo(orderInfoVo);</br>
        </span><span style="color: #0000ff;">int</span> n =<span style="color: #000000;"> purchaseDao.createOrderDetail(orderDetailLs);</br>
        </span><span style="color: #008000;">//</span><span style="color: #008000;">消息推送接口</span></br>
        pushNoticeService.pushNotice(order_id, "01"<span style="color: #000000;">);</br>
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> vo;</br>
    }</span></pre>
    
    复制代码
    复制代码
    /**
    * app端消息推送 B
    * @Description:
    *
    @param order_id
    *
    @param type
    *
    @author xingle
    * @data 2014-7-4 上午11:31:34
    */
    @Override
    @Transactional(value
    = "txManager", isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
    public void pushNotice(BigDecimal order_id, String type) {
    List
    <appNoticeVo> noticeLs = new ArrayList<appNoticeVo>();
    List
    <appNoticeDetailVo> noticeDtLs = new ArrayList<appNoticeDetailVo>();
    // 只针对好机会的订单处理
    List<noticeOrderVo> orderLs = pushNoticeDao.getOrderInfo(order_id);
    /**
    * 中间业务处理省略
    */
    pushNoticeDao.insertAppNotice(noticeLs);
    pushNoticeDao.insertAppNoticeDetail(noticeDtLs);
    }
    }
    复制代码

    如上,这里把creatOrder的方法称作A,pushNotice的方法称作B,A中调用B。A的事务传播性设为Propagation.REQUIRED,B的事务传播性也设为Propagation.REQUIRED,B中会沿用之前的事务继续,但是由于是在同一事务下,如果方法 B中的操作出错,比如在方法pushNoticeDao.insertAppNotice(noticeLs) 中写错语句,那么发现方法A也会失败,这和我们的要求不符。

    为了不影响原订单创建,这里把B传播性设为propagation = Propagation.REQUIRES_NEW,这样B出错并不会导致A也失败,但又出现一个新的问题,即B中

    :orderLs = pushNoticeDao.getOrderInfo(order_id) 列表查询不到结果,原来在同一个service下,上一方法还未提交结束。

    为了解决这一问题,故把B的调用放在action层中A方法完成之后,如下:

    复制代码
        @Description("营销活动生成订单")
    @RequestMapping(value
    = "/creatOrder", method = { RequestMethod.POST })
    public @ResponseBody CreatOrderByActyRetnVo creatOrder(HttpServletRequest request, HttpServletResponse response, @RequestBody CreatOrderByActyRecvVo recvVo) {
    CreatOrderByActyRetnVo vo
    = activityService.creatOrder(userId, recvVo);
    try {
    pushNoticeService.pushNotice(
    new BigDecimal(vo.getOrderId()),
    "01");
    }
    catch (Exception e) {
    logger.debug(
    "app端消息推送写入异常", e);
    }
    return vo;
    }
    复制代码

    问题得以解决。


    详见:解惑 spring 嵌套事务

  • 相关阅读:
    「考试」省选6
    「考试」省选5
    「考试」省选4
    「笔记」拉格朗日插值
    数学专测
    「笔记」$exlucas$
    「总结」$dp1$
    「总结」达哥数学专项
    「总结」筛法2
    「总结」莫反2
  • 原文地址:https://www.cnblogs.com/jpfss/p/9151095.html
Copyright © 2011-2022 走看看