• 热门专题

MES项目中出现的一个事务嵌套的使用场景

作者:wz1989  发布日期:2015-01-30 19:56:21
Tag标签:场景  事务  项目  
  • 昨天在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是单例的, 如果不改回来,其他代码要事务管理的时候,就没有作用了            
About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规