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

昨天在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

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

自定义Button供整个项目使用,一个项目中只用这一个Button即可

在做项目的过程中会发现经常需要自定义Button以便实现图片和文字的随意摆放,这样整个项目中就会有很多多余的类,具体的缺点我先列举几个场景. 1.一个button里面放置一个图片和一个文字,上面是图片,下面是文字,产品要求图片的尺寸必须是30*30,这时我们可以自定义一个button把图片尺寸写死.突然有一天又来了一个新的需求,图片要求40*40,又要新建一个类,突然有一天又来了一个需求,图片在下面,又要新建一个类,突然有一天又来了一个需求,图片的大小要根据屏幕的尺寸变化而变化,又新建了一个类,

在类库或winform项目中打开另一个winform项目的窗体

假设类库或winform项目为A,另一个winform项目为B.那麽在A中添加一个接口,里面有一个Show方法,然后在B中写一个类b继承这个接口,并重写这个方法,具体内容为弹出某个窗体.然后在A中另一个类a中实例化B中的b类,并把它赋给A中的接口,然后调用接口的Show方法就可以弹出B中指定的窗体. 需要注意的是项目A和项目B需要互相引入对方的EXE或DLL文件. 转自:http://blog.csdn.net/a1027/article/details/2766396 以下为代码部分: 1 n

自己在项目中写的一个Jquery插件和Jquery tab 功能

后台查询结果 PDFSearchResult实体类: [DataContract(Name = "PDFSearchResult")] public class PDFSearchResult { public PDFSearchResult(string title, string fileUrl) { Title = title; FileUrl = fileUrl; } [DataMember(Name = "title")] public string Ti

Eclipse中在android项目中出现新建一个Activity后,出现整个工程的报错以及包导入以后无法运行等等情况分析。

今天用Eclipse去写android项目,然后后面需要建一个Blank  Activity后,很正常的建立的,然后那个Activity是基于ActionBarAtivity,要导入v7,结果因为这个v7的原因,导致原来的导入包不见了,而且重新导入的时候,虽然工程开启没有报错误,但是接下来在运行的时候,结果运行不了,Logcat出现Classnotfound,但是之前的工程一点事都有.折磨了半天,终于发现错误所在,兼容性问题就不说了,说一下应该怎么解决这样的报错.那就是在新建的时候,你新建一个E

Eclipse中在android项目中出现新建一个Activity后,出现整个project的报错以及包导入以后无法执行等等情况分析。

今天用Eclipse去写android项目,然后后面须要建一个Blank  Activity后,非常正常的建立的.然后那个Activity是基于ActionBarAtivity,要导入v7,结果由于这个v7的原因,导致原来的导入包不见了.并且又一次导入的时候,尽管project开启没有报错误,可是接下来在执行的时候,结果执行不了.Logcat出现Classnotfound,可是之前的project一点事都有.折磨了半天,最终发现错误所在,兼容性问题就不说了,说一下应该怎么解决这种报错.那就是在新

最近项目中遇到了一个场景,其实很常见,就是定时获取接口刷新数据。那么问题来了,假设我设置的定时时间为1s,而数据接口返回大于1s,应该用同步阻塞还是异步?

初识setTimeout 与 setInterval 先来简单认识,后面我们试试用setTimeout 实现 setInterval 的功能 setTimeout 延迟一段时间执行一次 (Only one) 1 2 3 4 5 setTimeout(function, milliseconds, param1, param2, ...) clearTimeout() // 阻止定时器运行 e.g. setTimeout(function(){ alert("Hello"); }, 30

2016.7.5 记项目过程中犯的一个从未察觉的低级错误

今天在项目中遇到了一个很奇葩的问题,具体什么问题就不说了,找了一下午实在找不出来,百般无奈之时,看到了自己敲的一条不太顺眼的代码: if(0<i<31) 心想这样写好像不好,于是将其改成if((i>0)&&(i<31)),编译调试,之前出现的问题居然奇迹般的消失了.经过和同学探讨,得出以下别人都知道的结论: if(0<i<31),程序首先计算0<i,i的范围是0~51,当i>0时,(0<i) == true,在我使用的编译器里面,认为t

angular6项目中使用echarts图表的方法(有一个坑,引用报错)

1.安装相关依赖(采用的webpack) npm install ecahrts --save npm install ngx-echarts --save 2.angular.json 配置echarts路径 "scripts": [ "node_modules/echarts/dist/echarts.min.js", "node_modules/echarts/map/js/china.js", "node_modules/ech

现实项目中用户随意添加序号,如何用SQL解决序号连续性问题

前段时间,一直忙于学习golang语言,没有时间整理项目中用到的方法,今天趁着有空写下笔记. 项目中,遇到一个比较"刁钻"的需求:用户用Excel导入到系统里,每一行前面都有一个序号,序号分成两部分,如下所示: 左边部分是大序号,右边是小序号,类似于书籍目录那样,序号是由用户自己编写,而且用户可以随意在Excel序号插入任何新序号,用户不保证新增或者编辑的序号是否正确,我们要做的是检查这些序号. 以下是我的检查思路: 1.序号是否连续 我们要事先给用户做一个限制,在大序号后面添加小序号