Java ResultSet教程

时间:2020-02-23 14:36:49  来源:igfitidea点击:

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实例。
    它提供有关查询输出的列的类型和属性的信息。