最近在一個java調用oracle存儲過程的程序中,經行壓力測試老報java.sql.SQLException: Conntion is closed,間歇中冶也有java.sql.SQLException: Conntion is closed。如果對java調用oracle存儲過程不太清楚的可以查看http://tiantiankaixin.iteye.com/blog/770250,這里講的比較清楚了。
就這個錯誤我查看了網上的各種資料發現了有着兩種可能:
(1)
1 private static String sql = null; 2 String rtn = null; 3 4 @POST 5 //無參數傳入 6 public String RK_JSCX() throws Exception { 7 8 RK_JSCX_Response response = null; 9 List<RK_JSCX_Outtable> list = null; 10 Connection con = null; 11 CallableStatement cs = null; 12 ResultSet rs = null; 13 try { 14 15 //存儲過程 16 sql = "{call RK_JSCX(?,?)}"; 17 con = ConnectionUtils.getInstance().getConnect(); 18 19 if (con.isClosed()) { 20 throw new IllegalStateException("ERROR.THE CONNECTION ISCLOSED"); 21 } 22 23 cs = con.prepareCall(sql); 24 25 //傳出參數 26 cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR); //傳出參數 類型和CK_XQ中的要一致 27 cs.registerOutParameter(2, Types.VARCHAR); 28 29 //執行存儲過程 30 cs.execute(); 31 32 rs = (ResultSet) cs.getObject(1); 33 list = new ArrayList<RK_JSCX_Outtable>(); 34 while (rs.next()) { 35 36 RK_JSCX_Outtable out = new RK_JSCX_Outtable(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getInt(5), rs.getString(6)); 37 38 list.add(out); 39 } 40 String outInfo = cs.getString(2); 41 42 43 response = new RK_JSCX_Response(list, outInfo); 44 45 } catch (SQLException e) { 46 47 e.printStackTrace(); 48 49 } catch (Exception e) { 50 51 e.printStackTrace(); 52 53 }finally { 54 55 try { 56 if (rs != null) { 57 rs.close(); 58 if (cs != null) { 59 cs.close(); 60 } 61 if (con != null) { 62 con.close(); 63 } 64 } 65 } catch (SQLException e) { 66 67 System.out.println("Exception2"); 68 e.printStackTrace(); 69 } 70 } 71 72 return JSON.toJSONString(response); 73 }
調用存儲過程的時候需要打開資源:connection,CallableStatement,ResultSet 記得打開后全部關閉了,關閉順序和打開相反。如果順序錯了就會報java.sql.SQLException: Conntion is closed。
(2)在並發情況下,把connection,CallableStatement,ResultSet都設置成了成員變量而報錯,我就是犯了這個錯誤。其實應該設置為局部變量,原因我想了一下 conn.close();好像不是釋放鏈接,是關閉鏈接,而設成成員變量在多個請求同時訪問時會大量的數據庫連接無法釋放(特別是在設計不是很好的情況下)。當你取得鏈接到達你連接池設置中的數量后,鏈接就都被你關閉了。所以當你再次去取的時候,就會報錯。換句話說你每次取得的鏈接用完就關閉了,而沒有還給連接池。
