为什么 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 接口?
我有一个在 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 接口?