Java ResultSet教程
Java ResultSet接口是java.sql包的一部分。
它是JDBC框架的核心组件之一。
ResultSet对象用于访问从关系数据库检索的查询结果。
ResultSet维护指向查询结果的单行的光标/指针。
使用ResultSet提供的导航和获取方法,我们可以一个一个地迭代和访问数据库记录。
ResultSet也可以用于更新数据。
Java ResultSet层次结构
Java ResultSet类层次结构
上图显示了ResultSet在JDBC Framework中的位置。
可以通过使用Statement,PreparedStatement或者CallableStatement执行SQL查询来获得ResultSet。
AutoCloseable,Wrapper是ResultSet的超级接口。
现在,我们将看到如何在Java程序中使用ResultSet。
ResultSet示例
我们将使用MySQL作为示例。
使用下面的DB脚本来创建数据库和表以及一些记录。
create database empdb; use empdb; create table tblemployee (empid integer primary key, firstname varchar(32), lastname varchar(32), dob date); insert into tblemployee values (1, 'Mike', 'Davis',' 1998-11-11'); insert into tblemployee values (2, 'Josh', 'Martin', '1988-10-22'); insert into tblemployee values (3, 'Ricky', 'Smith', '1999-05-11');
让我们看下面的示例程序,从表中获取记录并将其打印在控制台上。
请确保项目类路径中有MySQL JDBC驱动程序。
package com.theitroad.examples; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Date; /** * Java Resultset Example of Retrieving records. * * @author hyman * */ public class ResultSetDemo { public static void main(String[] args) { String query = "select empid, firstname, lastname, dob from tblemployee"; Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root"); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { Integer empId = rs.getInt(1); String firstName = rs.getString(2); String lastName = rs.getString(3); Date dob = rs.getDate(4); System.out.println("empId:" + empId); System.out.println("firstName:" + firstName); System.out.println("lastName:" + lastName); System.out.println("dob:" + dob); System.out.println(""); } rs.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (Exception e) {} } } }
输出:
empId:1 firstName:Mike lastName:Davis dob:1998-11-11 empId:2 firstName:Josh lastName:Martin dob:1988-10-22 empId:3 firstName:Ricky lastName:Smith dob:1999-05-11
说明:
通过调用Statement实例上的executeQuery方法获得ResultSet。
最初,ResultSet的光标指向第一行之前的位置。ResultSet的next方法将光标移动到下一行。
如果还有其他行,则返回true,否则返回false。我们可以使用它提供的getter方法从ResultSet中获取数据。
例如getInt(),getString(),getDate()所有的getter方法都有两个变体。
第一个变体将列索引作为参数,第二个变体将列名称作为参数。最后,我们需要在ResultSet实例上调用close方法,以便正确清理所有资源。
结果集类型和并发
我们可以在创建Statement,PreparedStatement或者CallableStatement的实例时指定ResultSet的类型和并发性。
statement.createStatement(int resultSetType,int resultSetConcurrency)
1)仅转发(ResultSet.TYPE_FORWARD_ONLY)
这种类型的ResultSet实例只能从第一行到最后一行向前移动。
可以通过调用next()方法将ResultSet向前移动一行。
在创建Statement,PreparedStatement或者CallableStatement的实例时,我们可以获得这种类型的ResultSet。
Statement stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("select * from tbluser");
2)滚动不敏感(ResultSet.TYPE_SCROLL_INSENSITIVE)
滚动不敏感ResultSet可以向前和向后滚动。
也可以通过调用absolute()方法将其滚动到绝对位置。
但是它对数据更改不敏感。
它仅在执行查询并获得ResultSet时才具有数据。
它不会反映获得数据后对数据所做的更改。
Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("select * from tbluser");
3)敏感滚动(ResultSet.TYPE_SCROLL_SENSITIVE)
滚动敏感结果集可以向前和向后滚动。
也可以通过调用absolute()方法将其滚动到绝对位置。
但是它对数据更改很敏感。
它会反映打开时对数据所做的更改。
Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("select * from tbluser");
ResultSet并发
1)只读(ResultSet.CONCUR_READ_ONLY)
它是默认的并发模型。
我们只能对ResultSet实例执行只读操作。
不允许任何更新操作。
2)可更新(ResultSet.CONCUR_UPDATABLE)
在这种情况下,我们可以对ResultSet实例执行更新操作。
结果集方法
我们可以将ResultSet方法分为以下几类。
- 导航方法
- 读/写方法
- 设置器/更新器方法
- 其他方法– close()和getMetaData()
1. ResultSet导航方法
boolean absolute(int row)引发SQLException:此方法将ResultSet游标移动到指定的行,如果操作成功,则返回true。
afterLast()引发SQLException:此方法将ResultSet游标移动到最后一行之后的位置。
void beforeFirst()引发SQLException:此方法将ResultSet光标移动到第一行之前的位置。
boolean first()引发SQLException:此方法将ResultSet光标移动到第一行。
boolean last()引发SQLException:此方法将ResultSet光标移到最后一行。
boolean next()引发SQLException:此方法将ResultSet光标移到下一行。
boolean previous()引发SQLException:此方法将ResultSet光标移到上一行。
package com.theitroad.examples; import java.sql.*; /** * Java Resultset Example using navigational methods. * * @author hyman * */ public class ResultSetDemo { public static void main(String[] args) { String query = "select empid, firstname, lastname, dob from tblemployee"; Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root"); stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery(query); System.out.println("All the rows of table=>"); while (rs.next()) { //Go to next row by calling next() method displayData(rs); } System.out.println("Now go directly to 2nd row=>"); rs.absolute(2); //Go directly to 2nd row displayData(rs); System.out.println("Now go to Previous row=>"); rs.previous(); //Go to 1st row which is previous of 2nd row displayData(rs); rs.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (Exception e) { } } } public static void displayData(ResultSet rs) throws SQLException { System.out.println("empId:" + rs.getInt(1)); System.out.println("firstName:" + rs.getString(2)); System.out.println("lastName:" + rs.getString(3)); System.out.println("dob:" + rs.getDate(4)); System.out.println(""); } }
输出:
All the rows of table=> empId:1 firstName:Mike lastName:Davis dob:1998-11-11 empId:2 firstName:Josh lastName:Martin dob:1988-10-22 empId:3 firstName:Ricky lastName:Smith dob:1999-05-11 Now go directly to 2nd row=> empId:2 firstName:Josh lastName:Martin dob:1988-10-22 Now go to Previous row=> empId:1 firstName:Mike lastName:Davis dob:1998-11-11
2. ResultSet的Getter/Reader方法
int getInt(int columnIndex)引发SQLException:此方法将指定的columnIndex的值返回为int。
long getLong(int columnIndex)抛出SQLException:该方法返回指定columnIndex的值,只要long
字符串getString(int columnIndex)引发SQLException:此方法将指定的columnIndex的值作为String返回。
java.sql.Date getDate(int columnIndex)引发SQLException:此方法将指定columnIndex的值作为java.sql.Date返回
int getInt(String columnLabel)抛出SQLException:此方法将指定列名称的值作为int返回。
long getLong(String columnLabel)抛出SQLException:该方法返回指定列名的值,直到long。
String getString(String columnLabel)引发SQLException:此方法以String形式返回指定列名称的值。
java.sql.Date getDate(String columnLabel)引发SQLException:此方法以java.sql.Date的形式返回指定列名称的值。
ResultSet包含getter方法,这些方法返回其他原始数据类型,例如boolean,float和double。
它还具有从数据库中获取数组和二进制数据的方法。
3. ResultSet设置器/更新器方法
void updateInt(int columnIndex,int x)引发SQLException:此方法使用int值更新当前行的指定列的值。
void updateLong(int columnIndex,long x)引发SQLException:此方法使用long值更新当前行的指定列的值。
void updateString(int columnIndex,String x)引发SQLException:此方法使用String值更新当前行的指定列的值。
void updateDate(int columnIndex,java.sql.Date x)引发SQLException:此方法使用java.sql.Date值更新当前行的指定列的值。
void updateInt(String columnLabel,int x)引发SQLException:此方法使用int值更新当前行的指定列标签的值。
void updateLong(String columnLabel,long x)引发SQLException:此方法使用long值更新当前行的指定列标签的值。
void updateString(String columnLabel,String x)引发SQLException:此方法使用String值更新当前行的指定列标签的值。
void updateDate(String columnLabel,java.sql.Date x)引发SQLException:此方法使用java.sql.Date值更新当前行的指定columnLabel的值。
注意:设置器/更新器方法不会直接更新数据库值。
调用insertRow或者updateRow方法后,将插入/更新数据库值。
package com.theitroad.examples; import java.sql.*; /** * Java Resultset Example using updater methods. * * @author hyman * */ public class ResultSetUpdateDemo { public static void main(String[] args) { String query = "select empid, firstname, lastname, dob from tblemployee"; Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root"); stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery(query); System.out.println("Now go directly to 2nd row for Update"); if (rs.absolute(2)) { //Go directly to 2nd row System.out.println("Existing Name:" + rs.getString("firstName")); rs.updateString("firstname", "Tyson"); rs.updateRow(); } rs.beforeFirst(); //go to start System.out.println("All the rows of table=>"); while (rs.next()) { //Go to next row by calling next() method displayData(rs); } rs.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (Exception e) { } } } public static void displayData(ResultSet rs) throws SQLException { System.out.println("empId:" + rs.getInt(1)); System.out.println("firstName:" + rs.getString(2)); System.out.println("lastName:" + rs.getString(3)); System.out.println("dob:" + rs.getDate(4)); System.out.println(""); } }
输出:
Now go directly to 2nd row for Update Existing Name:Josh All the rows of table=> empId:1 firstName:Mike lastName:Davis dob:1998-11-11 empId:2 firstName:Tyson lastName:Martin dob:1988-10-22 empId:3 firstName:Ricky lastName:Smith dob:1999-05-11
4. ResultSet其他方法
void close()抛出SQLException:此方法释放与ResultSet实例关联的资源。
必须调用它,否则将导致资源泄漏。ResultSetMetaData getMetaData()引发SQLException:此方法返回ResultSetMetaData实例。
它提供有关查询输出的列的类型和属性的信息。