- 问题 : 使用注解配置
Spring Aop
的四种通知类型实现事务控制,出现如下问题 :
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Can't call rollback when autocommit=true
-
原因:由于四种通知类型的执行顺序与
xml
配置方式的差异 ,可以将注解配置的方式理解为一个bug
。 -
正常使用
xml
配置 四种通知类型的执行顺序是 : 前置通知 后置通知/异常通知(当出现异常时) 最终通知。这是一种正常的情况。
<aop:config>
<aop:pointcut id="pc" expression="execution(* com.lyp.service.impl.*.*(..))"/>
<aop:aspect id="txAspect" ref="txManager">
<aop:before method="beginTransaction" pointcut-ref="pc"/>
<aop:after-returning method="commitTransaction" pointcut-ref="pc"/>
<aop:after-throwing method="rollbackTransaction" pointcut-ref="pc"/>
<aop:after method="closeTransaction" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
- 使用注解配置四种通知类型的时候的执行顺序 :前置通知 最终通知 后置通知/异常通知(当出现异常时) 。此时最终通知优先于后置通知执行了,首先将连接释放,此时再进行提交,就是会出现上面的异常。
/**
* 开启事务
*/
@Before("pc()")
public void beginTransaction() {
try {
/* 设置事务提交方式为手动提交 */
System.out.println("开启事务");
cu.getTreadLocalConnection().setAutoCommit(false);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 回滚事务
*/
@AfterReturning("pc()")
public void rollbackTransaction() {
try {
/* 设置事务提交方式为手动提交 */
System.out.println("回滚事务...");
cu.getTreadLocalConnection().rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 提交事务
*/
@AfterThrowing("pc()")
public void commitTransaction() {
try {
System.out.println("提交事务....");
/* 设置事务提交方式为手动提交 */
cu.getTreadLocalConnection().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 释放连接
*/
@After("pc()")
public void closeTransaction() {
try {
/* 设置事务提交方式为手动提交 */
System.out.println("关闭事务....");
cu.getTreadLocalConnection().close();
cu.removeConn();
} catch (Exception e) {
e.printStackTrace();
}
}
- 解决办法:使用环绕通知替换上面的配置
@Around("pc()")
public Object aroundAdvice(ProceedingJoinPoint pjp) {
Object rs = null;
try {
Object[] args = pjp.getArgs();
// 开启事务
this.beginTransaction();
// 执行代码
rs = pjp.proceed(args);
// 提交事务
this.commitTransaction();
return rs;
} catch (Throwable t) {
// 回滚事务
this.rollbackTransaction();
throw new RuntimeException(t);
} finally {
this.closeTransaction();
}
}
网友评论