昨天在MES项目中,需要在业务逻辑的几个关键点记录错误信息,需要把错误信息写入数据表. 但是由于整个业务逻辑都是包在一个事务模板里面的
比如这样的:
WhhTransactionTemplate transactionTemplate2 = new WhhTransactionTemplate(true); transactionTemplate2.execute(new WhhTransactionCallback() { @SuppressWarnings({ "unchecked", "unused" }) @Override public Object doInTransaction(){ save_mes_do_materials_detail(batchDateList,para); matnrCostWithNothing(batchDateList,para,result,res); //省略.... logerror(para, "原辅料消耗上传 调用sap功能出错!" + invokeResult.getInvokeResultMessage(), "消耗上传"); //省略.... return null; } });
导致logerror方法也被包含在事务中,一旦业务出错,事务回滚,那么链logerror方法写入的错误信息也会被回滚,导致无法记录下错误日志.
这和平时的事务嵌套就不一样,一般都是内层事务加入外层事务的,这里就需要内层事务暂时退出事务管理才行.
这里就涉及到事务嵌套的问题, 外层事务是存在的这个就不用说了,那么此时logerror的逻辑应该要脱离事务环境才对,于是很自然的就想到应该使用
PROPAGATION_NOT_SUPPORTED 的传播特性.
之前分析过spring源码,知道在内层事务传播特性为PROPAGATION_NOT_SUPPORTED 的时候,会把外层事务挂起,把线程绑定的ConnectionHolder给清除掉,
导致内层事务里的方法需要获取Connection的时候,只能重新从dataSource获取 ,既然Connection不一样了,自然也就不受上层事务的影响.
于是把logerror方法修改如下
public void logerror(final Map para, final String info, final String errortype){ TransactionTemplate tempTemplate= DBConnectManager.getDefaultDBConnectBean().getTransactionTemplate(); //首先修改当前这个tempTemplate的传特性为PROPAGATION_NOT_SUPPORTED tempTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED ); tempTemplate.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { para.put("info", info); para.put("errortype", errortype); DataAdapter dataAdapter = new DataAdapter(); dataAdapter.insert("insert into mes_error_info (wid,pid,errorinfo,errortype) values($wid$,0,#info#,#errortype#)",para); return null; } }); //执行完之后 tempTemplate的传特性要改回PROPAGATION_REQUIRED tempTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED ); }
这样一来 记录错误信息的代码就不会受到外层事务的影响了,最后记得方法执行完,一定要把传播特性改回PROPAGATION_REQUIRED,毕竟tempTemplate是单例的,
如果不改回来,其他代码要事务管理的时候,就没有作用了
时间: 2024-12-11 05:58:36