(本博客用于记录自己在编程时遇到的一个很蠢的问题,可能对你的帮助不是很大)。 实现了基于动态代理处理JDBC异常时自动事务回滚,invoke方法时中的代码是
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log.trace("调用方法:" + method.getName()); //方法返回值 Object value; try{ // 将受代理的事务执行 // 创建并获取数据库连接,并设置为手动提交,开启事务 JdbcUtil.beginTransaction(); // 执行对应service方法,在service中会再次获取上面创建的连接 // 获取service执行的结果 value = method.invoke(serviceRunner, args); }catch (Exception ex) { //事务回滚 log.error("事务执行出现异常,回滚!"); JdbcUtil.rollbackTransaction(); throw ex; }finally { // 事务提交 JdbcUtil.commitTransaction(); // 事务完毕,结束事务 JdbcUtil.closeTransaction(); } return value; }可以看到,事物是会先提交再回滚的,但是实际上我在运行时出现了异常:Can’t call commit when autocommit=true 我仔细看了我的日志记录,复制如下:
开启事务,获取连接,关闭自动提交开启事务,获取连接,关闭自动提交获取连接,提交事务获取连接,结束事务获取连接,提交事务可以看到它获取了两次连接,然后有一个事物提交了之后,另一个事物还想要提交,结果连接已经关闭了。 经过排查我发现自己犯了一个很蠢的错误。由于是第一次尝试代理模式,所以我在Dao处也使用了同一个代理,导致service层调用dao层时开启了两次事物。 解决方式:在Dao工厂将Dao的代理删去即可。