未包装的连接是否被重用?

Is unwrapped connection reused?

我有一个 spring 组件,如下所示:

@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 方法中正确获取连接?那段代码能引起"connection leaks"吗?

我问这个是因为在某些时候我在日志中看到了类似这样的错误:Could not get JDBC Connection; nested exception is org.apache.tomcat.jdbc.pool.PoolExhaustedException。 (我不是在问如何解决这个错误或它意味着什么)

So my question is: I'm correctly getting the connection in execute method?

不,池 return 的连接代理而非真实连接代理(参见 ProxyConnection)。 而proxy的close方法是"overridden"到return连接池:

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 方法在实际连接上调用,而不是在代理上调用。连接未 return 发送到池中,最终池抛出 PoolExhaustedException

修复方法如下:

try (Connection connection = dataSource.getConnection()) { // proxy is returned to the pool
    SQLServerConnection c = connection.unwrap(SQLServerConnection.class));
    // Work with SQLServerConnection 
}

另外请记住,您应该将展开的连接保持在您获取它时的相同状态