开发者社区 问答 正文

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 1391 分享
分享
版权
举报
阿里云 AI 助理回答

根据您的描述,您在使用Spring框架管理事务,并且遇到了一个关于事务回滚的异常行为。首先,让我们澄清几个关键点以更好地理解问题:

  1. 事务传播行为:您提到的事务传播机制配置为REQUIRED。这意味着如果当前存在事务,则方法将会加入到这个事务中;如果不存在,则会创建一个新的事务。

  2. 代码示例:您的doTransaction方法内执行了两个数据库操作(doUpdate1doUpdate2),并且在两者之间抛出了一个未被捕获的RuntimeException。按照Spring的默认事务规则,当方法中抛出未检查异常(即继承自RuntimeException的异常)时,应该触发事务回滚。

  3. 问题现象:直接调用doTransaction方法时,如果抛出异常,A方法的操作能够正确回滚。但是,当通过callTransaction方法间接调用doTransaction,即使抛出异常,A方法的操作却没有回滚。

针对这个问题,有几个可能的原因:

  • 事务管理器配置问题:确保事务管理器配置正确,并且被正确地应用到了包含doTransaction方法的服务类上。请检查@Transactional注解是否正确放置在服务类或方法上,并且确认Spring扫描到了这个配置。

  • 异常被捕获处理:虽然您说callTransaction不处理任何异常,但请仔细检查是否有其他地方(比如AOP切面、全局异常处理器等)捕获并处理了这个异常,这可能会导致Spring认为事务可以正常提交而不是回滚。

  • 嵌套事务问题:由于callTransaction没有自己的事务声明(即它没有@Transactional注解),理论上它应该不会影响到内部调用的doTransaction方法的事务行为。但如果存在某些特定的AOP配置或者代理设置不当,可能导致事务上下文传递出现问题。

解决建议:

  • 确认@Transactional注解的使用是否正确无误,包括它的属性设置(如rollbackFor来指定需要回滚的异常类型,尽管对于未检查异常,默认情况下应当自动回滚)。

  • 检查整个调用链路中是否存在异常被捕获而未向上抛出的情况,确保异常能自然传播到事务管理器。

  • 查看Spring的日志输出,特别是与事务管理相关的日志,这有助于诊断事务开始、提交或回滚的详细过程,以及是否有任何错误或警告信息。

如果以上检查均未发现问题,可能需要更详细的配置信息和代码逻辑来进一步分析问题所在。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答