2016-01-21 159 views
0

我在preparedStatement中遇到問題。每當prepareStatement被創建並執行時打開遊標計數,並且它不會下降。 我正在關閉結果,每次執行後的語句。
爲了確保事情不會因爲其他代碼片段而發生,我創建了一個簡單的jsp並將代碼執行到其中。在使用PreparedStatement關閉結果集和語句後,Oracle不會刪除遊標

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 

請幫我如果我在這裏做錯了任何事情,請告訴我。

+1

試着使用這個:try-with-resources。 *在JDK7中,AutoCloseable列表包括java.sql.CallableStatement,Connection,PreparedStatement,Statement,ResultSet和* RowSet。* https://blogs.oracle.com/WebLogicServer/entry/using_try_with_resources_with – ibre5041

+0

目前,我們正在使用JDK6生產和我需要修復它在相同的版本。 –

回答

1

這是DBCP池中的一些問題,我們正在使用。它也被報道在下面的傑拉票。 https://issues.apache.org/jira/browse/DBCP-397

如果你仍想繼續使用同一個池版,解決方法是在WHERE子句中的PreparedStatement傳遞中使用的所有參數,或者乾脆代替它使用的聲明。

0

您使用的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循環。

+0

嗨,romg,我也一樣。代碼'JdbcUtils.closeQuietly(rs,pstmt)'是'public static final void closeQuietly(ResultSet rs,PreparedStatement ps){ \t \t closeQuietly(rs); \t \t closeQuietly(ps); \t} 公共靜態最終無效closeQuietly(PreparedStatement的PS){ \t \t如果(PS!= NULL){ \t \t \t嘗試{ \t \t \t \t ps.close(); \t \t \t}趕上(的SQLException E){ \t \t \t \t記錄器。錯誤(「關閉準備好的語句時出錯」,e); \t \t \t} \t \t} \t} 公共靜態最終無效closeQuietly(ResultSet的RS){ \t \t如果(RS!= NULL){ \t \t \t嘗試{ \t \t \t \t rs.close() ; \t \t \t}趕上(的SQLException E){ \t \t \t \t logger.error( 「錯誤關閉結果集時」,E); \t \t \t} \t \t} \t}' –

+0

我試圖關閉RS和手動stmt是。結果是相同的,即循環退出後剩餘的打開遊標。 –