JDBC ResultSet接口
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