JDBC ResultSet接口

时间:2020-01-09 10:35:21  来源:igfitidea点击:

java.sql.ResultSet接口表示我们通过执行数据库查询获得的数据。一旦获得ResultSet,就可以对其进行遍历以遍历记录。为了便于迭代,ResultSet对象维护一个游标,该游标指向其当前数据行。最初,光标位于第一行之前。 ResultSet中有一个next方法,它将光标移动到下一行,当ResultSet对象中没有更多行时,返回false。

创建和迭代结果集

我们可以从Statement对象获取ResultSet对象,它可以是普通Statement,PreparedStatement或者CallableStatement。

// From Statement
ResultSet rs = statement.executeQuery("Select * from Employee");

// From PreparedStatement
String selectSQL = "SELECT * FROM EMPLOYEE WHERE id = ?";
PreparedStatement prepStmt = connection.prepareStatement(selectSQL);
ResultSet rs = prepStmt.executeQuery();

// From CallableStatement
CallableStatement callableStatement = connection.prepareCall(
        "{call select_all_employee()}");
ResultSet rs = callableStatement.executeQuery();

一旦具有记录的ResultSet对象,就可以在while循环中使用next方法遍历该对象。

while(rs.next()){
  System.out.println("id: " + rs.getInt("id") + 
     " First Name: " + rs.getString("FIRST_NAME") + 
     " Last Name: " + rs.getString("LAST_NAME")+ 
     " Dept: " + rs.getString("DEPARTMENT")); 
}

ResultSet Java示例

在示例中,从Employee表中获取记录,然后迭代ResultSet以遍历记录。使用的数据库是MySql,模式是theitroad,使用的表是EMPLOYEE,其列为id,FIRST_NAME,LAST_NAME和DEPARTMENT。

如前所述,使用下一个方法迭代ResultSet。

为了从行中获取列值,可以使用不同类型的各种getter来传递列索引或者列名。请注意,列索引从1开始,例如,如果我们已执行查询从Employee中选择ID,first_name,last_name,department,则可以使用列索引来检索first_name

rs.getString(2);

或者使用列名

rs.getString(" FIRST_NAME")

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ResultSetDemo {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Load driver
      Class.forName("com.mysql.cj.jdbc.Driver");
      // connection object
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad", 
                   "root", "admin");
      // create Statement object
      Statement statement = connection.createStatement();
      ResultSet rs = statement.executeQuery("Select * from Employee");
      // Iterate through ResultSet
      while(rs.next()){
        System.out.println("id: " + rs.getInt("id") + 
           " First Name: " + rs.getString("FIRST_NAME") + 
           " Last Name: " + rs.getString("LAST_NAME")+ 
           " Dept: " + rs.getString("DEPARTMENT")); 
      }   
        
    }catch(ClassNotFoundException | SQLException e) {
       e.printStackTrace();
    }finally{
      if(connection != null){
        //close connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}

Java中的ResultSet类型

默认情况下ResultSet对象是不可更新的,即我们无法更新ResultSet的一部分的记录,默认情况下ResultSet的游标只能向前移动,我们只能对其进行一次迭代,并且只能从第一行迭代到最后一行。但是ResultSet中有一些字段可以更改默认行为并创建可滚动和/或者可更新的ResultSet。

ResultSet中用于使其可滚动的字段如下所示

  • ResultSet.TYPE_FORWARD_ONLY-指示ResultSet对象的类型的常数,其光标只能向前移动。

  • ResultSet.TYPE_SCROLL_INSENSITIVE –指示ResultSet对象类型的常数,该对象可以在向前和向后两个方向上滚动,但通常对ResultSet基础数据的更改不敏感。如果数据库中的数据被任何其他过程更改,则该更改将不会反映在ResultSet中存储的数据中。

  • ResultSet.TYPE_SCROLL_SENSITIVE-指示ResultSet对象类型的常数,该对象可在向前和向后两个方向上滚动,并且通常对ResultSet基础数据的更改敏感。如果数据库中的数据被任何其他进程更改,则该更改将反映在ResultSet中存储的数据中。

ResultSet并发模式

ResultSet中的字段,用于指定ResultSet中的数据可以更新还是只读。

  • ResultSet.CONCUR_READ_ONLY-指示并发模式为ResultSet对象只读的常数。我们只能读取不允许的数据更新操作。

  • ResultSet.CONCUR_UPDATABLE –指示可更新的ResultSet对象的并发模式的常数。

如果要更改默认行为,则可以在创建Statement对象时指定这些字段。例如,如果我们想要一个ResultSet可以在两个方向上移动但对更改不敏感并且是只读的。

Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

结果集可保存性

除了上述字段之外,我们还可以指定ResultSet是通过commit操作关闭还是保持打开状态。

  • CLOSE_CURSORS_AT_COMMIT –此常量指示在提交当前事务时将关闭具有此可保存性的打开的ResultSet对象。

  • HOLD_CURSORS_OVER_COMMIT –此常量指示在提交当前事务时,具有此可保存性的打开的ResultSet对象将保持打开状态。

可滚动的ResultSet Java示例

这是一个创建可滚动结果集的示例。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ResultSetDemo {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Load driver
      Class.forName("com.mysql.cj.jdbc.Driver");
      // connection object
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad", 
                   "root", "admin");
      // create Statement object   
      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
    		  							ResultSet.CONCUR_UPDATABLE);  
      ResultSet rs = statement.executeQuery("Select * from Employee");
      // Iterate through ResultSet
      while(rs.next()){
        System.out.println("id: " + rs.getInt("id") + 
           " First Name: " + rs.getString("FIRST_NAME") + 
           " Last Name: " + rs.getString("LAST_NAME")+ 
           " Dept: " + rs.getString("DEPARTMENT")); 
      }   
      // moving to 5th row
      rs.absolute(5);
      System.out.println("Record at 5th Row");
      System.out.println("id: " + rs.getInt("id") + 
              " First Name: " + rs.getString("FIRST_NAME") + 
              " Last Name: " + rs.getString("LAST_NAME")+ 
              " Dept: " + rs.getString("DEPARTMENT")); 
        
    }catch(ClassNotFoundException | SQLException e) {
       e.printStackTrace();
    }finally{
      if(connection != null){
        //close connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}

输出:

id: 2 First Name: John Last Name: McClane Dept: Police
id: 3 First Name: Luc Last Name: Deveraux Dept: Army
id: 4 First Name: Harry Last Name: Callahan Dept: Police
id: 5 First Name: Gordon Last Name: Gekko Dept: Finance
id: 10 First Name: Hyman Last Name: Cullinan Dept: Finance
id: 15 First Name: Ravi Last Name: Upadhyay Dept: Finance
id: 16 First Name: John Last Name: Trudaue Dept: Finance
id: 17 First Name: Ranjeet Last Name: Sharma Dept: Police
Record at 5th Row
id: 10 First Name: Hyman Last Name: Cullinan Dept: Finance

ResultSet中用于光标移动的方法

我们可以使用以下任何一种方法在ResultSet中移动光标。

  • absolute(int row)–将光标移动到此ResultSet对象中的给定行号。

  • afterLast()–将光标移动到该ResultSet对象的末尾,紧接在最后一行之后。

  • beforeFirst()–将光标移动到此ResultSet对象的前面,紧挨着第一行。

  • first()–将光标移动到此ResultSet对象的第一行。

  • last()–将光标移动到此ResultSet对象的最后一行。

  • moveToCurrentRow()–将光标移动到记住的光标位置,通常是当前行。

  • next()–将光标从其当前位置向前移动一行。

  • previous()–将光标移动到此ResultSet对象的上一行。

ResultSet中的更新程序方法

ResultSet中有各种更新程序方法,用于更新不同类型的数据。当ResultSet可更新时,将使用这些更新程序方法。首先,我们将使用updateXXX()方法更新列值,然后调用updateRow()更新派生rs的数据源表,或者调用insertRow()将新行插入结果集并最终插入数据源表。

可更新的ResultSet Java示例

这是一个使用ResultSet方法更新和插入行的示例。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ResultSetDemo {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Load driver
      Class.forName("com.mysql.cj.jdbc.Driver");
      // connection object
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad", 
                   "root", "admin");
      // create Statement object   
      Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
    		  							ResultSet.CONCUR_UPDATABLE);  
      ResultSet rs = statement.executeQuery("Select * from Employee");
      // Iterate through ResultSet
      while(rs.next()){
        System.out.println("id: " + rs.getInt("id") + 
           " First Name: " + rs.getString("FIRST_NAME") + 
           " Last Name: " + rs.getString("LAST_NAME")+ 
           " Dept: " + rs.getString("DEPARTMENT")); 
      }   
      // moving to 5th row and updating a column
      rs.absolute(5);
      System.out.println("Record at 5th Row");
      System.out.println("id: " + rs.getInt("id") + 
              " First Name: " + rs.getString("FIRST_NAME") + 
              " Last Name: " + rs.getString("LAST_NAME")+ 
              " Dept: " + rs.getString("DEPARTMENT")); 
      rs.updateString("LAST_NAME", "Reacher");
      rs.updateRow();
      System.out.println("Updated Record at 5th Row");
      System.out.println("id: " + rs.getInt("id") + 
              " First Name: " + rs.getString("FIRST_NAME") + 
              " Last Name: " + rs.getString("LAST_NAME")+ 
              " Dept: " + rs.getString("DEPARTMENT")); 
      // inserting a new row      
      rs.moveToInsertRow();  
      // Using column index          
      rs.updateString(2, "Dean"); 
      rs.updateString(3, "Jones");
      //Using Column name
      rs.updateString("Department", "Sports");
      rs.insertRow();
      rs.moveToCurrentRow();
    }catch(ClassNotFoundException | SQLException e) {
       e.printStackTrace();
    }finally{
      if(connection != null){
        //close connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}

输出:

id: 2 First Name: John Last Name: McClane Dept: Police
id: 3 First Name: Luc Last Name: Deveraux Dept: Army
id: 4 First Name: Harry Last Name: Callahan Dept: Police
id: 5 First Name: Gordon Last Name: Gekko Dept: Finance
id: 10 First Name: Hyman Last Name: Cullinan Dept: Finance
id: 15 First Name: Ravi Last Name: Upadhyay Dept: Finance
id: 16 First Name: John Last Name: Trudaue Dept: Finance
id: 17 First Name: Ranjeet Last Name: Sharma Dept: Police
Record at 5th Row
id: 10 First Name: Hyman Last Name: Cullinan Dept: Finance
Updated Record at 5th Row
id: 10 First Name: Hyman Last Name: Reacher Dept: Finance