使用 PreparedStatement 时,Oracle 在关闭结果集和语句后不会删除游标

Oracle doesn't remove cursors after closing result set and statement, while using PreparedStatement

我在 preparedStatement 中遇到问题。每次创建和执行 preparedStatement 时,打开游标计数都会增加,但不会减少。 我在每次执行后关闭结果语句。
只是为了确保事情不会由于其他一些代码而发生,我创建了一个简单的 jsp 并在其中执行了代码。

 Connection connection = null;
Set<Long> prodIds = new HashSet<Long>();
prodIds.add(5877462198L);
prodIds.add(782414147L);
prodIds.add(5547149987L);
prodIds.add(550424780L);
prodIds.add(5547045538L);
prodIds.add(5883926198L);
prodIds.add(5537432075L);
prodIds.add(81317072L);
prodIds.add(5618071249L);
prodIds.add(5630549908L);
prodIds.add(698964409L);
prodIds.add(822090000L);
prodIds.add(614679729L);
prodIds.add(5512339613L);
prodIds.add(81317068L);
prodIds.add(5688111900L);
prodIds.add(5512339611L);
prodIds.add(5894594380L);
prodIds.add(969040343L);
prodIds.add(827515204L);
prodIds.add(5626593095L);
prodIds.add(501511677L);
prodIds.add(1094656287L);
prodIds.add(5560791888L);
prodIds.add(641347103L);
prodIds.add(786034417L);
prodIds.add(774821382L);
prodIds.add(5599522282L);
prodIds.add(5591420268L);
prodIds.add(660541300L);
prodIds.add(82846941L);
prodIds.add(5529315772L);
prodIds.add(895683920L);
prodIds.add(5547045523L);
prodIds.add(801472476L);
prodIds.add(687163631L);
prodIds.add(5682795171L);
prodIds.add(5547045563L);
prodIds.add(687163630L);


 try {
        Class.forName("oracle.jdbc.driver.OracleDriver");
         connection = DataSources.getDefaultDataSource().getConnection();
        out.println("connected....!!");
     List<List<Long>> partitionedProductIdsList = Lists.partition(new ArrayList<Long>(prodIds), 1);
     for (List<Long> productIdsList : partitionedProductIdsList) {
             String sql = "SELECT * FROM RECLASSIFY_PRODUCTS_BULK_LOG WHERE  product_id = " + productIdsList.get(0);
                sql += "AND clsf_id = ? ";
             PreparedStatement pstmt = null;
             ResultSet rs = null;
             int paramIndex = 1;
             try {
                pstmt = connection.prepareStatement(sql);
                pstmt.setLong(paramIndex, 203L);
                rs = pstmt.executeQuery();
                while (rs.next()) {
                    out.println(rs.getLong("PRODUCT_ID"));
                }
            } catch (SQLException e) {
                out.println("Exception : " + e.getMessage() + "");
            } finally {
                JdbcUtils.closeQuietly(rs, pstmt);

            }
        }
     out.println("Closing the connection");
    } catch (Exception e) {
     out.println("Exception : " + e.getMessage() + "");
 }
finally {
     try {
         connection.close();
     }
     catch (SQLException e)
     {
         out.println("SQLException : " + e.getMessage() + "");
     }
 }

这是查询的结果:-

select a.value, s.username, s.sid, s.serial#
 from v$sesstat a, v$statname b, v$session s
 where a.statistic# = b.statistic# and s.sid=a.sid
 and b.name = 'opened cursors current' and machine = 'v-b10' order by    a.value desc

最初

VALUE USERNAME SID SERIAL# 610 UBDB 494 1485 4 UBDB 323 16275 2 UBDB 225 41357 0 UBDB 102 14729

加载后 jsp

VALUE   USERNAME    SID SERIAL#
687 UBDB    494 1485
4   UBDB    323 16275
2   UBDB    225 41357
0   UBDB    102 14729

请帮助我,如果我在这里做错了什么请告诉我。

您使用的 JdbcUtils.closeQuietly(rs, pstmt) 不工作。尝试手动关闭您的 rs 和 stmt:

if(rs != null){
  try{
    rs.close();
  }catch(Exception AllException){
    AllException.printStackTrace();
  }
}
if(pstmt != null){
  try{
    pstmt .close();
  }catch(Exception AllException){
    AllException.printStackTrace();
  }
}

此外,为了利用绑定机制,您应该只在 for 循环之外创建和关闭准备好的语句一次。

这是我们正在使用的 DBCP 池中的一些问题。在以下 jira ticket 中也有报道。 https://issues.apache.org/jira/browse/DBCP-397

如果您仍想继续使用相同的池版本,解决方法是将 where 子句中使用的所有参数都传递到 PreparedStatement 中,或者简单地使用 Statement 代替它。