Spring的JdbcTemplate自动关闭连接

来源:https://blog.csdn.net/partner4java/article/details/7012196


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




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

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

显然,我们在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. public static void releaseConnection(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. /** 
  23. * Actually close the given Connection, obtained from the given DataSource. 
  24. * Same as {@link #releaseConnection}, but throwing the original SQLException. 
  25. * <p>Directly accessed by {@link TransactionAwareDataSourceProxy}. 
  26. * @param con the Connection to close if necessary 
  27. * (if this is <code>null</code>, the call will be ignored) 
  28. * @param dataSource the DataSource that the Connection was obtained from 
  29. * (may be <code>null</code>) 
  30. * @throws SQLException if thrown by JDBC methods 
  31. * @see #doGetConnection 
  32. */  
  33. public static void doReleaseConnection(Connection con, DataSource dataSource) throws SQLException {  
  34.     if (con == null) {  
  35.         return;  
  36.     }  
  37.   
  38.     if (dataSource != null) {  
  39.         ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);  
  40.         if (conHolder != null && connectionEquals(conHolder, con)) {  
  41.             // It's the transactional Connection: Don't close it.  
  42.             conHolder.released();  
  43.             return;  
  44.         }  
  45.     }  
  46.   
  47.     // Leave the Connection open only if the DataSource is our  
  48.     // special SmartDataSoruce and it wants the Connection left open.  
  49.     if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {  
  50.         logger.debug("Returning JDBC Connection to DataSource");  
  51.         con.close();  
  52.     }  
  53. }  

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

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


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

猜你喜欢

转载自blog.csdn.net/binglong_world/article/details/80774877