如何解决使用DataSource对象实例化JdbcTemplate对象时,它是否打开连接?
我的构造函数中有一段代码如下:
<guid2 isPermaLink="true">
<value>http://example.com/abc</value>
</guid2>
我的问题是:创建JdbcTemplate对象时,它是否从连接池获取连接并保持使用状态?
我问这个问题是因为我想避免实例化Foo对象占用池中的一个连接并保留它的情况。这样的安排将意味着仅从bean实例化就使我的连接池迅速耗尽。
解决方法
您实际上在这篇文章中有两个不同的问题。
让我们一次吃一次。
使用DataSource对象实例化JdbcTemplate对象时,它是否打开连接?
否,创建JdbcTemplate对象不会打开与数据库的连接。它甚至不会创建它。
我们可以看到afterPropertiesSet()
方法的源代码,该方法在JdbcTemplate(DataSource dataSource)
构造函数中被调用:
@Override
public void afterPropertiesSet() {
if (getDataSource() == null) {
throw new IllegalArgumentException("Property 'dataSource' is required");
}
if (!isLazyInit()) {
getExceptionTranslator();
}
}
实际上打开的时刻是您调用JdbcTemplate API的一种查询方法时。
例如execute(ConnectionCallback<T> action)
方法如下:
@Override
@Nullable
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action,"Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource());
try {
// Create close-suppressing Connection proxy,also preparing returned Statements.
Connection conToUse = createConnectionProxy(con);
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
// Release Connection early,to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
DataSourceUtils.releaseConnection(con,getDataSource());
con = null;
throw translateException("ConnectionCallback",sql,ex);
}
finally {
DataSourceUtils.releaseConnection(con,getDataSource());
}
}
在实际问题中要问的第二个问题是:
JdbcTemplate查询方法API是重用JDBC连接还是每次创建新连接?
让我们看一下DataSourceUtils.getConnection(obtainDataSource());
方法,然后依次尝试 doGetConnection(dataSource)
。后者的源代码如下:
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource,"No DataSource specified");
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(fetchConnection(dataSource));
}
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
logger.debug("Fetching JDBC Connection from DataSource");
Connection con = fetchConnection(dataSource);
if (TransactionSynchronizationManager.isSynchronizationActive()) {
try {
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
}
else {
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse,dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != conHolder) {
TransactionSynchronizationManager.bindResource(dataSource,holderToUse);
}
}
catch (RuntimeException ex) {
// Unexpected exception from external delegation call -> close Connection and rethrow.
releaseConnection(con,dataSource);
throw ex;
}
}
return con;
}
最后,我们看到:
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(fetchConnection(dataSource));
}
return conHolder.getConnection();
}
就在这里。您可以清楚地看到如果存在,则表示该连接已被获取并重新使用。
See the full code关于不存在连接的创建方式。
JdbcTemplate API的other methods以类似的方式工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。