使用注解配置aop,如图所示
@Pointcut("execution(* cn.service.impl.*.*(..))")
private void pt1() {
}
/**
* 开启事务
*/
@Before("pt1()")
public void beginTranction() {
try {
connectionUtils.getThreadConnection().setAutoCommit(false);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 提交事务
*/
@AfterReturning("pt1()")
public void commit() {
try {
connectionUtils.getThreadConnection().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 回滚事务
*/
@AfterThrowing("pt1()")
public void rollback() {
try {
connectionUtils.getThreadConnection().rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 释放连接,并不是真正的关闭,而是将连接还回池中
*/
@After("pt1()")
public void release() {
try {
connectionUtils.getThreadConnection().close();
connectionUtils.removeConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
运行后,报错如图所示
java.sql.SQLException: Can't call commit when autocommit=true
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:930)
at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1535)
at com.mchange.v2.c3p0.impl.NewProxyConnection.commit(NewProxyConnection.java:803)
at cn.utils.TransactionManager.commit(TransactionManager.java:39)
经过查找资料,发现这是由于使用注解配置aop时,事务的执行顺序出错导致,@After在@AfterReturning之前执行,导致connection被释放掉,故被认为事务已被自动提交,用环绕通知配置即可解决这一问题,配置如下
@Around("pt1()")
public Object aroundAdvice(ProceedingJoinPoint pjp) {
Object reValue = null;
try {
//获得参数
Object[] args = pjp.getArgs();
//开启事务
this.beginTranction();
//执行方法
reValue = pjp.proceed(args);
//提交事务
this.commit();
//返回值
return reValue;
} catch (Throwable e) {
//回滚
this.rollback();
throw new RuntimeException(e);
} finally {
//释放
this.release();
}
}
记得将之前的事务通知注销
本文详细介绍了如何使用注解配置AOP实现事务管理,包括@Pointcut定义切入点、@Before开启事务、@AfterReturning提交事务、@AfterThrowing回滚事务及@After释放连接。并针对运行时出现的Can't call commit when autoCommit=true错误,提供了解决方案,通过使用@Around环绕通知重新配置事务流程。
758

被折叠的 条评论
为什么被折叠?



