为什么 OracleConnection 没有返回到池中?

Why OracleConnection isn't returned to the pool?

我有一个在 Internet 上没有找到的问题。

我正在尝试使用 ojdbc6 连接到数据库。我从 jndi

获取资源
<Resource name="jdbc/ds_conn" type="javax.sql.DataSource" maxTotal="10" 
url="jdbc:oracle:thin:@someDB.com:1731/nameDB" 
driverClassName="oracle.jdbc.OracleDriver" 
connectionProperties="SetBigStringTryClob=true; 
oracle.net.READ_TIMEOUT=5000;" password="pass" username="user"
maxWait="10000" maxIdle="300" maxActive="1000" auth="Container"/>

使用方法

public OracleConnection getConnection() throws OracleDatabaseReaderConnectionException, NamingException {

    Context initialContext = null;
    try {
        initialContext = new InitialContext();
        DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/ds_conn");
        OracleConnection connection = (OracleConnection) dataSource.getConnection().unwrap(OracleConnection.class);
        return connection;
    } catch (NamingException | SQLException e) {
        e.printStackTrace();
        throw new OracleDatabaseReaderConnectionException(e.getMessage());
    } finally {
        if (initialContext != null) {
            initialContext.close(); 
        }
    }
}

接下来我正在执行查询

try (OracleConnection connection = getConnection();
    OraclePreparedStatement preparedStatement = (OraclePreparedStatement) connection.prepareStatement(sqlQuery);
        OracleResultSet resultSet = (OracleResultSet) preparedStatement.executeQuery()) {

    //some actions

} catch (OracleDatabaseReaderConnectionException | SQLException | NamingException e) {
        throw new OracleDatabaseReaderException(e.getMessage());
}

}

据我所知,这是连接到数据库并执行查询的常见操作。

但是连接没有关闭。正如您在我的 jndi 中看到的那样,我有参数 maxTotal="10"。因此,在 10 个查询池变满之后,其他查询只是在等待池中的一个位置。我不知道如何解决这个问题并关闭连接。也许我在将 Connection 转换为 OracleConnection 等时有冲突?也许你的资源不太好用?

问题是您要关闭内部 OracleConnection 而不是外部包装。不同之处在于前者 确实 关闭了连接,而关闭包装器只会 return 连接到池。

(OracleConnection) dataSource.getConnection().unwrap(OracleConnection.class);

此处调用 unwrap() 会导致池包装器消失,您不能再对其调用 close。解决此问题的一种方法是仅在启动 try-with-resources 后调用 unwrap(),如下所示:

try (Connection connection = getConnection()) {  // Now the pooled connection will be "closed"
    OracleConnection oc = connection.unwrap(OracleConnection.class);

    try(OraclePreparedStatement ps ...) ...

但这不是很好,至少如果你需要在很多地方这样做的话。是否绝对有必要在这里使用特定于 Oracle 的 类 而不是 JDBC 接口?