我有一个像下面这样的弹簧组件:
@Component
class FooComponent {
@Autowired
private DataSource dataSource;
public void execute() {
try (SQLServerConnection connection = dataSource.getConnection().unwrap(SQLServerConnection.class)) {
// some logic here with connection
}
}
}
我必须解开连接,因为我正在使用Microsoft JDBC驱动程序中的某些API(如果我只是传递dataSource.getConnection()
,它将抛出异常)。
所以我的问题是:
我可以通过execute
方法正确连接吗?这段代码会导致“连接泄漏”吗?
我之所以这样问,是因为有时我在日志中看到类似Could not get JDBC Connection; nested exception is org.apache.tomcat.jdbc.pool.PoolExhaustedException
的错误。 (我不是在问如何解决此错误或其含义)
答案 0 :(得分:2)
所以我的问题是:我可以在execute方法中正确获得连接吗?
否,该池返回连接代理而不是真实的代理(请参见ProxyConnection)。
代理的close
方法被“重写”以将连接返回到池:
if (compare(CLOSE_VAL,method)) {
if (connection==null) return null; //noop for already closed.
PooledConnection poolc = this.connection;
this.connection = null;
pool.returnConnection(poolc);
return null;
}
}
但是当您这样做
try (SQLServerConnection connection = dataSource.getConnection().unwrap(SQLServerConnection.class))
close
方法在真实连接上调用,而不是在代理上调用。连接不会返回到池,最终池会抛出PoolExhaustedException
。
以下是解决方法:
try (Connection connection = dataSource.getConnection()) { // proxy is returned to the pool
SQLServerConnection c = connection.unwrap(SQLServerConnection.class));
// Work with SQLServerConnection
}
还请记住,您应该将未包装的连接保持在与获取连接相同的状态