前言:
问题是这样的。我们使用的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抓到了,然后回滚数据库,这样就会导致一个问题,数据库总是不能操作成功。而又不报错。。记录再次避免下次犯错。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于