开发者社区> 问答> 正文

Mybatis整合Spring配置事务无效问题 : 配置报错 

现象:
在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)

展开
收起
kun坤 2020-06-03 17:31:23 1363 0
1 条回答
写回答
取消 提交回答
  • 再加这一句<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配置接口一致。这边因为是沿用的老的配置,所以也不会选用注解。

    2020-06-05 13:20:57
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关实验场景

更多