最近使用ResultSet发现一些问题,集中表现为
多次执行 stmt.executeQuery方法,获得的数据集有时为空,有时提醒 结果集已耗尽,有时调用 first()方法等提示 对只转发结果集的无效操作: first
经系统研究 ResultSet特性后,总结如下:
1.ResultSet rs = stmt.executeQuery(sql);
当让stmt来返回一个结果集的时候,前面一个ResultSet会自动关闭。
即在执行stmt.executeQuery的时候,会自动关闭上一次stmt.executeQuery的结果集。
所以,我们用:
ResultSet rs = stmt.executeQuery(sql);
while(){……}
rs2 = stmt.executeQuery(sql2);
while(){……}
rs3 = stmt.executeQuery(sql3);
while(){……}
是没有问题的,因为我们在用下一个结果集的时候,没再去前一个中拿数据。
但是,在有嵌套的时候:
while (rs.next()) {
String sql2 = "select * from role_areamap";
rs2 = stmt.executeQuery(sql2);
while (rs2.next()) {
System.out.println(rs.getString(1));
}
System.out.println(rs.getInt(1));
}
就会报错了。
解决方法:1,再新建一个Statement
每次获取结果集用不同的 Statement 对象去执行sql
2.用Jdbc3.0的新特性:Statement.KEEP_CURRENT_RESULT
在Statement建立时 stmt = conn.createStatement();
使用的是默认参数(结果集类型为ResultSet.TYPE_FORWARD_ONLY),这种类型的结果集只能通过rs.next();方法逐条读取,使用其他读取方法时就会报错。如果需要执行一些其他或复杂的移动结果集指针的操作就要使用其它参数。
如,更改如下,可解决:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
各参数介绍:
1. ResultSet.TYPE_FORWARD_ONLY (默认方式,略)
2. ResultSet.TYPE_SCROLL_INSENSITIVE 双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。
3. ResultSet.TYPE_SCROLL_SENSITIVE 双向滚动,并及时跟踪数据库里的更新,以便更改ResultSet中的数据。
4. ResultSet.CONCUR_READ_ONLY 只读取ResultSet
5. ResultSet.CONCUR_UPDATABLE 用ResultSet更新数据库