展开的连接是否被重用?

时间:2018-12-14 09:33:56

标签: java jdbc spring-jdbc

我有一个像下面这样的弹簧组件:

@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的错误。 (我不是在问如何解决此错误或其含义)

1 个答案:

答案 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 
}

还请记住,您应该将未包装的连接保持在与获取连接相同的状态