提示错误:
com.microsoft.sqlserver.jdbc.SQLServerException:结果集已关闭
错误引起原因:
ResultSet内嵌套使用ResultSet引起的
问题的引起:
我做了一个简单的demo:
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
ResultSet rs_2 = null;
try {
conn = DbPool.getConnection();
stat = conn.createStatement();
rs = stat.executeQuery(sql);
while (rs.next()) {
…………….省略。。。。
rs_2= stat.executeQuery(sql_test);
while(rs.next()){
……..省略
}
}
错误就这样引起了。
可以很直接的看出:首先我用Statement对象产生了一个ResultSet对象rs,遍历此对象,取出一个值作为条件拼装了另一个SQL,然后又用同一个Statement对象产生了第二个ResultSet对象rs_2,错误就此产生了-------外层的rs只执行了一次,循环倒第二个值时就提示错误:结果集已经关闭!
错误原因:
在java里每个ResultSet结果集都需要一个单独的statement来支撑,如果想使用多个Result就必须使用创建多个statement。
解决办法:
1.创建2个Statement对象,嵌套的内外层各用一个;
2.不要采用ResultSet的嵌套-----首先遍历外层Resulet,把结果集放入一个List,然后遍历这个List,在这个List中在使用Statement对象重新产生了ResultSet对象
延伸理解:
执行了Statement的任何一个方法,比如execute(),executeUpdate(),executeQuery()等方法,这时候它的返回值就和这个Statement绑定了,如果要使用此返回值,在使用期间就不能再利用这个Statement做其他事情了,因为它是独占的,一旦在此期间被使用,则返回值自动会被清空(对于execute(),executeUpdate()的返回值就无所谓了,因为她们返回的都是一个boolean或int类型的值,不是一个List,没有遍历的必要)。。。
所有,当遇到我们通过一个Statement的executeQuery()得到一个ResultSet对象时候,如果在遍历这个ResultSet期间想再次使用Statement执行另一个SQL,其一是另一个SQL用Statement2(新产生的Statement对象)执行,其二是把ResultSet对象里面的值放到一个集合中,然后遍历集合,此时因为ResultSet是没用的,所有Statement可以使用;------但是我们可以看出,第二种做法有自身的局限性,因为一旦这个ResultSet对象非常大,把它放入一个集合显然是不明智的。。。。