最近在一个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();好像不是释放链接,是关闭链接,而设成成员变量在多个请求同时访问时会大量的数据库连接无法释放(特别是在设计不是很好的情况下)。当你取得链接到达你连接池设置中的数量后,链接就都被你关闭了。所以当你再次去取的时候,就会报错。换句话说你每次取得的链接用完就关闭了,而没有还给连接池。