spring事务回滚问题

刚刚接到一个上家公司同事的一个电话,问我为什么service方法事务不会滚了,日志打印了,调用webservice报错。

我让他把这个调用执行webservice的方法截图发给我,如下:
 
public Object[] send(String operationName,Object[] params,String endPoint) throws Exception {
		Object[] results = null;
		Client client = null;
		try {
			// 获取外部服务注册信息
			Map<String, ExtWebserviceInfo> extMap = (Map<String, ExtWebserviceInfo>)SimpleCacheUtils.get(ExtWebService.WEBSERVICE);
			// 获取操作名称
			if (!ToolUtil.isNullOrEmpty(extMap)) {
				// 获取服务方法名
				String methodName = extMap.get(operationName).getServiceValue();
				LOGGER.info("获取到方法标识为*"+operationName+"的操作名"+methodName);
				// 创建client
				client = new Client(new URL(endPoint));
				LOGGER.info("监测到请求"+endPoint+"服务"+methodName+"操作方法的动作...");
				// 执行调用
				results = client.invoke(methodName, params);
				LOGGER.info("向"+endPoint+"服务"+methodName+"操作方法发出的请求成功...");
			}
		} catch (Exception e) {
			LOGGER.info("向"+endPoint+"服务标识为"+operationName+"的操作方法发出的请求出现异常..."+e.getLocalizedMessage());
			throw(Exception)new Exception().initCause(e);
		} finally{
			if(client != null){
				client.close();
			}
		}
		return results;
	}

  

 
这个方法是一个调用执行webservice的方法,并返回执行结果给调用者,就是上面这个方法报错。我一看到这个代码,中有try catch,我想一定是这个方法中把异常给拦截了,service中捕获不到异常,导致aop拦截不到异常信息,导致事务不回滚。
但是仔细一看发现这个方法虽然捕获了异常,但是捕获后有重新抛出异常。
 
} catch (Exception e) {
	LOGGER.info("向"+endPoint+"服务标识为"+operationName+"的操作方法发出的请求出现异常..."+e.getLocalizedMessage());
	throw(Exception)new Exception().initCause(e);
} finally{

   

这不是又抛出异常了吗?应该没有问题了啊。
仔细分一下,就发现问题就出在这里,它抛出的是一个Exception,而spring在事务回滚时,是只对runtimeException或者其子类的异常才会回滚。
而且这里抛出的是一个Exception,别人调用的时候肯定提示要trycatch,如果一不小心,catch中没有重新抛出runtimeException,那就会出现事务不回滚的问题,而且此问题一般不易被发现。
 
总结一下:
1、spring做aop事务拦截的一般都会配置在service层;
2、service层一般情况下不能trycatch,有时候有检查行异常,那么就往上抛,如果又不想抛,那么就trycatch中在throw new RuntimeException("出错了!!!");
3、service层抛出的异常必须是runtimeException或者其子类的异常。
 
作者:徐飞
出处:www.cnblogs.com/xumanbu/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/xumanbu/p/4760583.html