关于手动调用SqlSessionTemplate的connection,关闭问题
sqlSessionTemplate的原理
阅读源码发现sqlSessionTemplate里声明了一个代理,所有的增删改查方法都通过代理来实现
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
这里通过代理模式来设计的,重点类:SqlSessionInterceptor
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
当我们通过sqlSessionTemplate.getConnection()调用的时候,实际上通过代理类来实现,我们注意到代理类的finally方法里有一个释放连接的操作,因此当调用getConnection()结束以后,自动释放掉了连接,所以正确取得连接的方法应该是:
this.st =sqlSessionTemplate;
Connection connection = SqlSessionUtils.getSqlSession(
this.st.getSqlSessionFactory(), this.st.getExecutorType(),
this.st.getPersistenceExceptionTranslator()).getConnection()