下面是我在开发中遇到一个事务使用错误案例
try { // buisness operation ut = Trans.getUserTransaction(); ut.begin(); if ("add".equals(actionType)) { addAccutor(moduleName, productId, liabId, accutor, nextExecuteOrder); } else if ("delete".equals(actionType)) { deleteAccutor(moduleName, productId, liabId, listId); } else if ("changeInputSource".equals(actionType)) { changeInputSource(moduleName, inputSource, listId); } else if ("moveup".equals(actionType)) { moveUpAccutor(moduleName, listId); } else if ("movedown".equals(actionType)) { moveDownAccutor(moduleName, listId); } ut.commit(); // load Data loadData(moduleName, request, form, productId, liabId); return mapping.findForward("AccutorBenefit");} catch (Exception e) { if (ut != null) { try { ut.rollback(); } catch (Exception e1) { throw ExceptionFactory.parse(e1); } } throw ExceptionFactory.parse(e);}
上面代码会有几种执行情况:
没异常发生时,不会有任何问题(这好像是废话);
有异常发生时,若异常发生在ut.commit之前没有问题;
若在执行loadData(moduleName, request, form, productId, liabId)发生异常,开始执行异常捕获,首先执行事务回滚,这是事务早已回滚,所以抛出No active Transaction.
这就导致最后抛出的是异常1,而在这之前抛出的异常2被虚拟机丢了,这和bruce eckel在thinking in java中讲到的java异常缺陷类似,都是丢掉前面的异常,抛出一个不相干异常.
改正方式:
1.其实这个地方不需要使用事务,删掉事务代码
2.把commit放到return之前执行
总结:
这里有两点值得我们关注:
1.这种错误的使用事务方式,导致了问题,以及改正方式
2.错误使用java异常机制的场景,vm丢掉了异常.
异常1
java.lang.IllegalStateException: No active Transaction at com.evermind.server.ApplicationServerTransactionManager.rollback(ApplicationServerTransactionManager.java:398) at com.company.pub.util.internal.DBTransaction.rollback(DBTransaction.java:108) at com.company.lf.product.ctrl.accutor.AccutorBenefitAction.process(AccutorBenefitAction.java:74) at com.company.pub.framework.GenericAction.execute(GenericAction.java:250) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482) at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at com.company.pub.framework.XssFilter.doFilter(XssFilter.java:96) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:16) at com.company.pub.framework.AppFilter.doFilter(AppFilter.java:83) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:600) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:790) at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:208) at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:125) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)
异常2
java.lang.NullPointerException at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:141) at com.company.lf.product.bo.product.MaintainModule.loadData(MaintainModule.java:231) at com.company.lf.product.ds.productlife.DataMaintainDSImpl.loadData(DataMaintainDSImpl.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at com.company.pub.framework.internal.DSProxy.invoke(DSProxy.java:98) at $Proxy5.loadData(Unknown Source) at com.company.lf.product.ds.productlife.DataMaintainDSDelegate.loadData(DataMaintainDSDelegate.java:52) at com.company.lf.product.ctrl.accutor.AccutorBenefitAction.loadData(AccutorBenefitAction.java:346) at com.company.lf.product.ctrl.accutor.AccutorBenefitAction.process(AccutorBenefitAction.java:65) at com.company.pub.framework.GenericAction.execute(GenericAction.java:250) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482) at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at com.company.pub.framework.XssFilter.doFilter(XssFilter.java:96) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:16) at com.company.pub.framework.AppFilter.doFilter(AppFilter.java:83) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:600) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:790) at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:208) at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:125) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)