1.SqlSessionTemplate的构造函数,根据传入的SqlSessionFactory和ExecutorType创建一个Spring管理的SqlSession,并生成SqlSession的动态代理对象
1 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, 2 PersistenceExceptionTranslator exceptionTranslator) { 3 4 notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); 5 notNull(executorType, "Property 'executorType' is required"); 6 7 this.sqlSessionFactory = sqlSessionFactory; 8 this.executorType = executorType; 9 this.exceptionTranslator = exceptionTranslator; 10 //这里使用了jdk的动态代理,为SqlSession创建了代理对象 11 this.sqlSessionProxy = (SqlSession) newProxyInstance( 12 SqlSessionFactory.class.getClassLoader(), 13 new Class[] { SqlSession.class }, 14 new SqlSessionInterceptor()); 15 }
2.创建一个名为SqlSessionInterceptor的InvocationHandler实现类,当调用SqlSession的代理对象的方法时,会调用这个 InvocationHandler实现类的invokd方法,这里,SqlSessionInterceptor中实现了对SqlSession的释放
1 private class SqlSessionInterceptor implements InvocationHandler { 2 @Override 3 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 4 SqlSession sqlSession = getSqlSession( 5 SqlSessionTemplate.this.sqlSessionFactory, 6 SqlSessionTemplate.this.executorType, 7 SqlSessionTemplate.this.exceptionTranslator); 8 try { 9 Object result = method.invoke(sqlSession, args); 10 if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { 11 // force commit even on non-dirty sessions because some databases require 12 // a commit/rollback before calling close() 13 sqlSession.commit(true); 14 } 15 return result; 16 } catch (Throwable t) { 17 Throwable unwrapped = unwrapThrowable(t); 18 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { 19 // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 20 //如果遇到异常,释放SqlSession 21 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); 22 sqlSession = null; 23 Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); 24 if (translated != null) { 25 unwrapped = translated; 26 } 27 } 28 throw unwrapped; 29 } finally { 30 //最后,如果SqlSession不为空,释放SqlSesssion 31 if (sqlSession != null) { 32 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); 33 } 34 } 35 } 36 }
3.通过SqlSession的代理对象来执行相关的增删改查方法
1 @Override 2 public int insert(String statement) { 3 //通过SqlSessionTemplate构造函数中生成的SqlSession的动态代理对象来执行 insert 操作 4 return this.sqlSessionProxy.insert(statement); 5 } 6 7 @Override 8 public int delete(String statement) { 9 //通过SqlSessionTemplate构造函数中生成的SqlSession的动态代理对象来执行 delete 操作 10 return this.sqlSessionProxy.delete(statement); 11 } 12 13 @Override 14 public int update(String statement) { 15 //通过SqlSessionTemplate构造函数中生成的SqlSession的动态代理对象来执行 update 操作 16 return this.sqlSessionProxy.update(statement); 17 } 18 19 @Override 20 public <T> T selectOne(String statement, Object parameter) { 21 //通过SqlSessionTemplate构造函数中生成的SqlSession的动态代理对象来执行 selectOne 操作 22 return this.sqlSessionProxy.<T> selectOne(statement, parameter); 23 }
4.由于SqlSessionTemplate通过代理的方式帮我们维护了SqlSession的生命周期(close,rollback,comit这些),所以我们不能显示的调用close方法
1 @Override 2 public void close() { 3 //不可以对Spring管理的SqlSession执行close方法 4 throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession"); 5 }
5.在SpringBoot项目中实测SqlSessionTemplate的方法执行,执行完方法后,会释放相应的SqlSession资源