Spring的JdbcTemplate使用,是否还需要手工或者aop指定关闭conn连接( 使用JdbcTemplate是否需要关闭连接)...

JdbcTemplate类使用DataSource得到一个数据库连接。然后,他调用StatementCreator实例创建要执行的语句。下一步,他调用StatementCallBack完成。
一旦StatementCallBack返回结果,JdbcTemplate类完成所有必要清理工作关闭连接。如果StatementCreator或StatementCallBack抛出异常,JdbcTemplate类会捕获他们,并转换为Spring数据访问异常。

Spring的JdbcTemplate使用,是否还需要手工或者aop指定关闭conn连接( 使用JdbcTemplate是否需要关闭连接)...



看一个JdbcTemplate里面的比较核心的一个方法:

  1. //-------------------------------------------------------------------------
  2. // Methods dealing with prepared statements
  3. //-------------------------------------------------------------------------
  4. publicObject execute(PreparedStatementCreator psc, PreparedStatementCallback action)
  5. throwsDataAccessException {
  6. Assert.notNull(psc,"PreparedStatementCreator must not be null");
  7. Assert.notNull(action,"Callback object must not be null");
  8. if(logger.isDebugEnabled()) {
  9. String sql = getSql(psc);
  10. logger.debug("Executing prepared SQL statement"+ (sql !=null?" ["+ sql +"]":""));
  11. }
  12. Connection con = DataSourceUtils.getConnection(getDataSource());
  13. PreparedStatement ps =null;
  14. try{
  15. Connection conToUse = con;
  16. if(this.nativeJdbcExtractor !=null&&
  17. this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
  18. conToUse =this.nativeJdbcExtractor.getNativeConnection(con);
  19. }
  20. ps = psc.createPreparedStatement(conToUse);
  21. applyStatementSettings(ps);
  22. PreparedStatement psToUse = ps;
  23. if(this.nativeJdbcExtractor !=null) {
  24. psToUse =this.nativeJdbcExtractor.getNativePreparedStatement(ps);
  25. }
  26. Object result = action.doInPreparedStatement(psToUse);
  27. handleWarnings(ps);
  28. returnresult;
  29. }
  30. catch(SQLException ex) {
  31. // Release Connection early, to avoid potential connection pool deadlock
  32. // in the case when the exception translator hasn't been initialized yet.
  33. if(pscinstanceofParameterDisposer) {
  34. ((ParameterDisposer) psc).cleanupParameters();
  35. }
  36. String sql = getSql(psc);
  37. psc =null;
  38. JdbcUtils.closeStatement(ps);
  39. ps =null;
  40. DataSourceUtils.releaseConnection(con, getDataSource());
  41. con =null;
  42. throwgetExceptionTranslator().translate("PreparedStatementCallback", sql, ex);
  43. }
  44. finally{
  45. if(pscinstanceofParameterDisposer) {
  46. ((ParameterDisposer) psc).cleanupParameters();
  47. }
  48. JdbcUtils.closeStatement(ps);
  49. DataSourceUtils.releaseConnection(con, getDataSource());
  50. }
  51. }

显然,我们在finally里面看到了关闭调用,在看看这个关闭调用方法内部:
  1. /**
  2. * Close the given Connection, obtained from the given DataSource,
  3. * if it is not managed externally (that is, not bound to the thread).
  4. * @param con the Connection to close if necessary
  5. * (if this is <code>null</code>, the call will be ignored)
  6. * @param dataSource the DataSource that the Connection was obtained from
  7. * (may be <code>null</code>)
  8. * @see #getConnection
  9. */
  10. publicstaticvoidreleaseConnection(Connection con, DataSource dataSource) {
  11. try{
  12. doReleaseConnection(con, dataSource);
  13. }
  14. catch(SQLException ex) {
  15. logger.debug("Could not close JDBC Connection", ex);
  16. }
  17. catch(Throwable ex) {
  18. logger.debug("Unexpected exception on closing JDBC Connection", ex);
  19. }
  20. }
  21. /**
  22. * Actually close the given Connection, obtained from the given DataSource.
  23. * Same as {@link #releaseConnection}, but throwing the original SQLException.
  24. * <p>Directly accessed by {@link TransactionAwareDataSourceProxy}.
  25. * @param con the Connection to close if necessary
  26. * (if this is <code>null</code>, the call will be ignored)
  27. * @param dataSource the DataSource that the Connection was obtained from
  28. * (may be <code>null</code>)
  29. * @throws SQLException if thrown by JDBC methods
  30. * @see #doGetConnection
  31. */
  32. publicstaticvoiddoReleaseConnection(Connection con, DataSource dataSource)throwsSQLException {
  33. if(con ==null) {
  34. return;
  35. }
  36. if(dataSource !=null) {
  37. ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
  38. if(conHolder !=null&& connectionEquals(conHolder, con)) {
  39. // It's the transactional Connection: Don't close it.
  40. conHolder.released();
  41. return;
  42. }
  43. }
  44. // Leave the Connection open only if the DataSource is our
  45. // special SmartDataSoruce and it wants the Connection left open.
  46. if(!(dataSourceinstanceofSmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
  47. logger.debug("Returning JDBC Connection to DataSource");
  48. con.close();
  49. }
  50. }

主要下面这几行代码:
  1. // Leave the Connection open only if the DataSource is our
  2. // special SmartDataSoruce and it wants the Connection left open.
  3. if(!(dataSourceinstanceofSmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
  4. logger.debug("Returning JDBC Connection to DataSource");
  5. con.close();
  6. }

哦,可以看到大部分情况下是自动关闭,除非你使用的SmartDataSource,且SmartDataSource指定了允许关闭。


有些时候,你引入了JdbcTemplate或者DaoSupport,但是有时还需要自己额外的拿到conn进行操作,如下:
jdbcTemplate.getDataSource().getConnection()
那么,你应该就需要关闭连接了