问题描述:
1,Connection是Statement的工厂,一个Connection可以生产多个Statement。
2,PreparedStatement,Statement是ResultSet的工厂,一个PreparedStatement,Statement却只能对应一个ResultSet(它们是一一对应的关系),但是同一个PreparedStatement和Statement可以及连续执行executeUpdate,execute除了返回ResultSet。
所以在一段程序里要用多个ResultSet的时候,必须再Connection中获得多个Statement,然后一个Statement对应一个ResultSet。在获取待生成的静态报表时采用连接数据库后创建了Statement对象并调用executeQuery(sql)方法返回ResultSet结果集,然后循环取出相应的记录。山寨测试代码如下:- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.Statement;
- import java.util.ArrayList;
- public class ResultSetTest {
- public static void main(String[] args) {
- String sql1=" select * from LKG_SR_EXCEL_TASK ";
- Connection conn=null;
- Statement stmt=null;
- ResultSet rs=null;
- ResultSet rsProc=null;
- try{
- Class.forName("oracle.jdbc.driver.OracleDriver");
- conn=DriverManager.getConnection("jdbc:oracle:thin:@192.168.23.45:1521:ORABI","portal","portal123");
- stmt=conn.createStatement();
- rs=stmt.executeQuery(sql1);
- int i = 0;
- while(rs.next()){
- System.out.println("i = "+ i++);
- rsProc=stmt.executeQuery(sql1)<span style="color:#000000;">;</span>
- int j =0;
- while(rsProc.next()){
- System.out.println("j = "+ j++);
- }
- }
- }catch(Exception e){
- System.out.println("数据库连接失败!");
- }finally{
- try{
- if(rs!=null){
- rs.close();
- }
- if(stmt!=null){
- stmt.close();
- }
- if(conn!=null){
- conn.close();
- }
- }catch(Exception e){
- System.out.println("数据库连接关闭失败!");
- }
- }
- }
- }
rs结果集中应该为多条数据,然而rs.next()只能取出集合中的第一条,但是rsProc.next()去记录是正常的。
问题解决的方式:
1.新增一个statement对象Statement stmt2=null;
2.将rsProc=stmt.executeQuery(sql1);修改如下:
stmt2 = conn.createStatement();
rsProc=stmt2.executeQuery(sql1);
3.在finally中添加如下:
if(stmt2!=null){
stmt2.close();
}
程序运行就正常了。
经思考之后,原因如下:
statement用于执行静态 SQL 语句并返回它所生成结果的对象。在默认情况下,同一时间每个 Statement 对象只能打开一个 ResultSet 对象(既同一个Statement打开的ResultSet只有一个记录指针)。因此创建SQL statement在执行sql中的流程,如果读取一个 ResultSet 对象与读取另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的了前 ResultSet 对象,则Statement 接口中的所有执行方法都会隐式关闭它。这里的ResultSet对象是默认的, ResultSet 对象不可更新,仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更新的 ResultSet 对象。以下代码片段(其中 con 为有效的 Connection 对象)演示了如何生成可滚动且不受其他更新影响的、可更新的结果集。
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
修改前的rsProc=stmt.executeQuery(sql1);中stmt并没有重新创建,因此rsProc对象地址没有发生变化。在rsProc循环取记录的之后,对象中的指示记录的指针已经指向结果集尾部,因而结果集rs再次next()的时候返回的是false,即只取出结果的第一条记录。