一个由于spring事务引起的bug

本贴最后更新于 4014 天前,其中的信息可能已经时移世改

前言:

      问题是这样的。我们使用的spring管理事务,但是这个事务里面嵌套了很多其他的注入的service来进行数据库操作。其中一个service(1)调另外一个service(2)去操作数据库,在service(1)中将异常捕捉,但是数据库总是回滚。。

问题分析:

      抱着这样的疑问去跟代码了。先上几段代码

        	ticketService.refundRequest(order.getOrderSource(),orderId,subOrderId,order.getOrderNo(),updateAirTicketParamVO.getYgActionTypeCode(),updateAirTicketParamVO.getApplyForCause());
        	airticketDetailDao.updateReApplyOrder(updateAirTicketParamVO);
			orderStatusConditionService.updateOrderStatus(orderId, new String[] { subOrderId }, OrderOperate.RE_APPLY_FOR.getCode(), sysUser);
    		try {<br>                           //这是第二个service可以看到进行了数据库操作。并且在最外层捕捉了异常,打出log日志
				postDataToWebSoftService.updateSoftOrder(orderId,updateAirTicketParamVO.getAirTicketId().toString());
			} catch (Exception e) {
				logger.info("----软终端订单更新接口异常--"+order.getOrderNo()+e.getMessage());
			}

接下来再继续跟进postDataToWebSoftService.updateSoftOrder ,看看里面有什么,代码如下

 public String updateSoftOrder(String  orderId,String ticketId)throws Exception{
		 try {
			Order order = orderDao.get(Long.valueOf(orderId));
			 Airticketdetail air=airticketDetailDao.get(Long.valueOf(ticketId));
				Map<String, String> paramMap = new HashMap<String, String>();
				paramMap.put("method","updateOrderInfo" );
				paramMap.put("reqCanal","{\"system\":\"YWXT\",\"version\":\"\"}");
				paramMap.put("req","{\"subStatusVos\":[{\"subOrderNo\":\""+air.getOrderItemNo()+"\",\"subOrderStatus\":\""+air.getTicketStatus()+"\"}],\"orderNo\":\""+order.getOrderNo()+"\",\"orderStatus\":\""+order.getOrderStatus()+"\"}");
				String url=CoreConstants.getProperty("webSoft.post.orderInfo", defaultValue);
				 logger.info("--------接口地址"+url);
				 HttpClientHelper httpClientHelper=new HttpClientHelper();
				 for(int i=0;i<3;i++){
					String result=httpClientHelper.sendPost(paramMap, url, CONNECTION_TIMEOUT, SOTIMEOUT);
						PostResultVo postResultVo=JsonUtil.getDTOObj(result, PostResultVo.class);
							if(SUCCESS.equals(postResultVo.getResultCode())){
								logger.info("updateorderinfo post successful!");
								break;
							}else{
								i++;
								logger.info("Updateorderinfo post fail!"+result);
							}
					}
		} catch (Exception e) {
			logger.info("Updateorderinfo post fail!更新软终端接口失败"+e.getMessage());

throw new BusinessException("更新软终端接口失败"+e.getMessage());

}
			 return null;
	    }

看着红色的代码,这种写法很逆天不是么?,在嵌套比较深的service捕捉异常,然后又抛出一个异常(相当于没有捕捉,所以在这里抛出了一个异常),然后在比较外层的地方捕捉异常(见第一段代码)。一切看起来没有什么问题。抛出,捕捉,但是我们来看看事务配置文件如下:

<aop:config>
		<aop:advisor advice-ref="tx-Advice"
			pointcut="execution(* com.newtouch.platform..service..*Service*.*(..)) 
			|| execution(* com.test.service..*Service*.*(..))
			|| execution(* cn.com.besttone.reservation.service..*Service*.*(..))
			|| execution(* cn.com.besttone.reservation.ws.service..*Service*.*(..))
			|| execution(* cn.com.besttone.reservation.ws.service.impl..*WebService*.*(..))
			|| execution(* cn.com.besttone.notification.service..*Service*.*(..))
			|| execution(* cn.com.besttone.orderprocess.service..*Service*.*(..))
			|| execution(* cn.com.besttone.orderprocess.autoassign..*Service*.*(..))
			|| execution(* cn.com.besttone.delivery.service..*Service*.*(..))
			|| execution(* cn.com.besttone.customer.service..*Service*.*(..))
			|| execution(* cn.com.besttone.organization.service..*Service*.*(..))
			|| execution(* cn.com.besttone.crm.service..*Service*.*(..))
			|| execution(* cn.com.besttone.sp.service..*Service*.*(..)) 
			|| execution(* cn.com.besttone.manage.service..*Service*.*(..))
			|| execution(* cn.com.besttone.finance.service..*Service*.*(..))
			|| execution(* cn.com.besttone.product.service..*Service*.*(..))
			|| execution(* cn.com.besttone.report.service..*Service*.*(..))"/>
	</aop:config>

总结:

      在service层的每个方法都用spring进行了事务管理。这样就导致了一个问题,我们自己捕捉异常,和spring捕捉异常的先后问题,结果很明显。比较深的service一抛出异常,还没等外面的service捕捉他就被spring抓到了,然后回滚数据库,这样就会导致一个问题,数据库总是不能操作成功。而又不报错。。记录再次避免下次犯错。

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 17 关注
  • 事务管理
    3 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...