现象:
在Service中有两个方法doTransaction(调用更新方法A、B,在A和B之间抛出RuntimeEx)和callTransaction。callTransaction调用doTransaction。且仅有doTransaction配置上了事务,callTransaction方法不处理任何异常。
在controller中单独调用doTransaction,有异常A是可以回滚的,但是如果在controller中调用callTransaction,doTransaction抛出异常直到controller,发现doTransaction方法中的A方法没有回滚。事务传波机制配置为REQUIRED
配置如下:
spring-mybatis.xml
<!-- 拦截器方式配置事物 --> <tx:advice id="transactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="doTransaction" propagation="REQUIRED" rollback-for="java.lang.Exception" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* com.forg..service..*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config>
Service如下
public boolean doTransaction(String p1,String p2){
boolean a = testDAO.doUpdate1(p1);
if(a){
throw new RuntimeException("抛出异常");
}
boolean b = testDAO.doUpdate2(p2);
return a && b;
}
public boolean callTransaction(String p1,String p2){
// try{ return doTransaction(p1,p2); // }catch(Exception e){ // System.out.println("doTransaction_exception!"); // throw new RuntimeException("抛出异常"); // return false;
// } }
调用Controller
public String testTransction(@RequestParam(value="p1",required=true)String p1, @RequestParam(value="p2",required=true) String p2){ if(("p111").equals(p1)){ if(ts.doTransaction(p1, p2)){//这里是可以回滚update1的 return "OK"; } return "NOT OK"; } try { if(ts.callTransaction(p1, p2)){//这里却不可以! return "OK"; } } catch (Exception e) { System.out.println("callTransaction_exception"); } return "NOT OK"; }
请各位大牛帮忙看下,不知道是什么原因导致的?
是到service级别的 ?还是我对事务传播机制理解有误?
下面是日志
直接调用callTransaction
[DEBUG] [org.mybatis.spring.SqlSessionUtils]Creating a new SqlSession kan>plugin... [DEBUG] [org.mybatis.spring.SqlSessionUtils]SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e10020] was not registered for synchronization because synchronization is not active kan>plugin... kan>plugin... kan>plugin... [DEBUG] [org.mybatis.spring.transaction.SpringManagedTransaction]JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3ffcfd14] will not be managed by Spring [DEBUG] [com.forg.com.test.update1]==> Preparing: UPDATE t_1 SET CNT = ? WHERE ID =1 [DEBUG] [com.forg.com.test.update1]==> Parameters: p112(String) [DEBUG] [com.forg.com.test.update1]<== Updates: 1 [DEBUG] [org.mybatis.spring.SqlSessionUtils]Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e10020] 一月 07, 2015 2:25:43 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() for servlet [springMVC] in context with path [/forgweb] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: 抛出异常] with root cause java.lang.RuntimeException: 抛出异常 at com.forg.test.service.TransactionTestService.doTransaction(TransactionTestService.java:32)
直接调用 doTransaction
kan>plugin... [DEBUG] [org.mybatis.spring.SqlSessionUtils]Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3ccb117c] kan>plugin... kan>plugin... kan>plugin... [DEBUG] [org.mybatis.spring.transaction.SpringManagedTransaction]JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3ffcfd14] will be managed by Spring [DEBUG] [com.forg.com.test.update1]==> Preparing: UPDATE t_1 SET CNT = ? WHERE ID =1 [DEBUG] [com.forg.com.test.update1]==> Parameters: p111(String) [DEBUG] [com.forg.com.test.update1]<== Updates: 1 [DEBUG] [org.mybatis.spring.SqlSessionUtils]Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3ccb117c] [DEBUG] [org.mybatis.spring.SqlSessionUtils]Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3ccb117c] [DEBUG] [org.mybatis.spring.SqlSessionUtils]Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3ccb117c] 一月 07, 2015 2:26:27 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() for servlet [springMVC] in context with path [/forgweb] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: 抛出异常] with root cause java.lang.RuntimeException: 抛出异常 at com.forg.test.service.TransactionTestService.doTransaction(TransactionTestService.java:32)
再加这一句<tx:method name="*" propagation="SUPPORTS" read-only="true" />,你的 callTransaction才能走事物,才能实现,你调callTransaction调doTransaction中的A方法回滚######回复 @开源中国驻联合国理事 : 这样配置理论上是满足的,但是就如我上面配置的一样,理论上应该可以,但是实际上却没有起效果。######回复 @kanlianhui : 额,<tx:method name="callTransaction" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" /> 这样配置的话在doTranaction是内部事务,而callTransaction是外部事物,这样不相互影响,不就达到你的要求了吗???######我描述下需求吧:一个service两个方法a,b.外部control调用方法a,方法a调用方法b,希望方法b中所有数据库操作是一个事务,但是方法a不受b中事务影响。现在配置如上,b中事务却没有回滚######回复 @kanlianhui : 额,你直接说需求就得了,要一步一步问,概述一下:你的意思是在一个Service Method里面嵌套两个其他的Service Method 但是这两个Service Method的方法直接的事物又互相不影响,对吗??######回复 @开源中国驻联合国理事 : 这样是可以的,效果和直接加在callTransaction上是一样的。因为真实情况中callTransaction在调用doTransaction之前有其他数据库操作,且不想跟随doTransaction一同回滚。请问还有其他办法么?######在写操作的方法商家@Transactional######回复 @CrazyHarry : 额,我现在就是用的AOP的配置方法,且存在问题。######回复 @kanlianhui : 那就只能使用aop配置方法了######多谢回答,用注解方式也试过了,效果与上面的XML配置接口一致。这边因为是沿用的老的配置,所以也不会选用注解。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。