ResultSet是JDBC中的一个接口,用于表示由数据库执行查询操作后返回的结果集。使用ResultSet接口,可以访问查询结果的当前行,并可以逐行移动结果集,从而让我们能够对结果集中的每行数据进行处理。在JDBC中,ResultSet接口由Statement.executeQuery()方法或PreparedStatement.executeQuery()方法返回。
使用ResultSet接口时,通常是以以下步骤进行操作:
- 将光标移动到结果集的第一行
- 访问当前行的数据
- 在结果集中移动光标
- 释放资源
现给出一个完整的基础示例:
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JdbcResultSetExample {
static String user = "YourName";
static String password = "YourPassword";
static String url = "jdbc:mysql://localhost:3306/jdbcdata";
static String className = "com.mysql.cj.jdbc.Driver";
// 获取数据库连接操作
public Connection getJDBCConnection() throws Exception{
Class.forName(className);
Connection connection = DriverManager.getConnection(url, user, password);
if(connection != null) {
return connection;
}
return null;
}
@Test
public void resultSetTest() throws Exception{
// 获取连接
Connection conn = getJDBCConnection();
if(conn != null){
// 待执行的SQL语句
String sql = "select job_id, job_title, min_salary, max_salary from jobs where min_salary > ? and max_salary < ?";
// 预编译
PreparedStatement preparedStatement = conn.prepareStatement(sql);
// 设置参数
preparedStatement.setInt(1,8000);
preparedStatement.setInt(2,20000);
// 执行SQL语句,获取结果集
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
// 获取一个对象的信息
String job_id = resultSet.getString("job_id");
String job_title = resultSet.getString(2);
int min_salary = resultSet.getInt("min_salary");
int max_salary = resultSet.getInt(4);
// 输出
System.out.println(job_id + " " + job_title + " " + min_salary + " " + max_salary) ;
}
// 关闭
conn.close();
preparedStatement.close();
resultSet.close();
}
}
}
运行结果:
AC_MGR Accounting Manager 8200 16000
FI_MGR Finance Manager 8200 16000
MK_MAN Marketing Manager 9000 15000
结果集
SQL语句从数据库中查询获取数据并将数据返回到结果集中。SELECT语句就是一个经典例子,它从一个数据库中选择行记录,并显示在一个结果集中。ResultSet接口就表示一个数据库查询的结果集。
一个ResultSet对象控制着一个光标执行当前行的结果集。“结果集”是指包含在ResultSet对象中的行和列的数据。
ResultSet接口的方法可划分为三类:
- 导航方法:用于移动光标
- 获取方法:查看被光标所指向的当前行的列中的数据。
- 更新方法:用于更新当前行的列中的数据,更新的同时也会影响到数据库中的数据。
光标的移动是基于ResultSet属性。我们在生成ResultSet对象的同时也会生成ResultSet属性。我们通过连接对象所提供的下述方法即可获得ResultSet对象:
- createStatement(int RSType, int RSConcurrency)
- prepareStatement(String SQL, int RSType, int RSConcurrency)
- prepareCall(String sql, int RSType, int RSConcurrency)
上述参数中的RSType用于表示返回的结果集类型,具体见下表:
结果集类型
类型 | 描述 |
---|---|
ResultSet.TYPE_FORWARD_ONLY | 光标只能在结果集中向前移动。 |
ResultSet.TYPE_SCROLL_INSENSITIVE | 光标可以向前和向后移动。当结果集创建后,其他人对数据库的操作不会影响结果集的数据。 |
ResultSet.TYPE_SCROLL_SENSITIVE. | 光标可以向前和向后移动。当结果集创建后,其他人对数据库的操作会影响结果集的数据。 |
结果集并发性
RSConcurrency参数用于指定结果集的并发类型,具体见下表:
并发性 | 描述 |
---|---|
ResultSet.CONCUR_READ_ONLY | 创建一个只读结果集,这是默认的值。 |
ResultSet.CONCUR_UPDATABLE | 创建一个可修改的结果集。 |
结果集导航
S.N. | 方法 & 描述 |
---|---|
1 | public void beforeFirst() throws SQLException 将光标移动到第一行之前。 |
2 | public void afterLast() throws SQLException 将光标移动到最后一行之后。 |
3 | public boolean first() throws SQLException 将光标移动到第一行。 |
4 | public void last() throws SQLException 将光标移动到最后一行。 |
5 | public boolean absolute(int row) throws SQLException 将光标移动到指定的第 row 行。 |
6 | public boolean relative(int row) throws SQLException 将光标移动到当前指向的位置往前或往后第 row 行的位置。 |
7 | public boolean previous() throws SQLException 将光标移动到上一行,如果超过结果集的范围则返回 false。 |
8 | public boolean next() throws SQLException 将光标移动到下一行,如果是结果集的最后一行则返回 false。(常用) |
9 | public int getRow() throws SQLException 返回当前光标指向的行数的值。 |
10 | public void moveToInsertRow() throws SQLException 将光标移动到结果集中指定的行,可以在数据库中插入新的一行。当前光标位置将被记住。 |
11 | public void moveToCurrentRow() throws SQLException 如果光标处于插入行,则将光标返回到当前行,其他情况下,这个方法不执行任何操作。 |
例如之前介绍的例子:
ResultSet resultSet = preparedStatement.executeQuery();
// 不断导航到当前光标的下一行,直到光标达到最后一行
while (resultSet.next()){
// 具体操作
}
结果集查看
ResultSet接口中含有几十种从当前行获取数据的方法,每个可能的数据类型,ResultSet接口都有一个get方法用于获取数据,并且每个get方法都有两种调用方式:
- 通过列名
- 通过列的索引,从1开始。
例如上面介绍的例子:
String sql = "select job_id, job_title, min_salary, max_salary from jobs where min_salary > ? and max_salary < ?";
while (resultSet.next()){
// 获取一个对象的信息
String job_id = resultSet.getString("job_id"); // 通过列名获取数据
String job_title = resultSet.getString(2);// 通过列的索引
int min_salary = resultSet.getInt("min_salary");
int max_salary = resultSet.getInt(4);
// 输出
System.out.println(job_id + " " + job_title + " " + min_salary + " " + max_salary) ;
}
结果集的更新
ResultSet 接口包含了一系列的更新方法,该方法用于更新结果集中的数据。
与结果集的get方法一样,结果集的更新update方法也有两种调用方式:
- 通过列名
- 通过列的索引
例如要更新当前行的String列的数据,可以使用下面两种方法进行更新或修改:
S.N. | 方法 & 描述 |
---|---|
1 | public void updateString(int columnIndex, String s) throws SQLException 将指定列的字符串的值改为 s。 |
2 | public void updateString(String columnName, String s) throws SQLException 类似于前面的方法,不同之处在于指定的列是用名字来指定的,而不是它的索引。 |
同样的,要更新一个int类型的列,调用updateInt方法就行了。但上述所提到的更新方式只能修改结果集中的数据,并不会影响数据库中的数据,要想修改数据库中的数据,可以使用下述几个方法:
S.N. | 方法 & 描述 |
---|---|
1 | public void updateRow() 通过更新数据库中相对应的行来更新当前行。 |
2 | public void deleteRow() 从数据库中删除当前行。 |
3 | public void refreshRow() 在结果集中刷新数据,以反映数据库中最新的数据变化。 |
4 | public void cancelRowUpdates() 取消对当前行的任何修改。 |
5 | public void insertRow() 在数据库中插入一行。本方法只有在光标指向插入行的时候才能被调用。 |
练习
练习使用的都是employess表,数据库的数据在JDBC学习一中已给出,答案在最后的所有代码里。
- 查询薪资大于等于10000的所有员工的姓名first_name和last_name、电话号码phone_number和salary
- 随机生成(1~250)员工id(employee_id),若员工存在,则将该员工的薪资提高10%,并输出提高前和提高后的信息(fist_name,last_name,salary,email,phone_number),否则,输出“No information about (此处补充输入的ID) was found in the database”
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Random;
import java.util.Scanner;
public class JdbcResultSetExample {
static String user = "YourName";
static String password = "YourPassword";
static String url = "jdbc:mysql://localhost:3306/jdbcdata";
static String className = "com.mysql.cj.jdbc.Driver";
public Connection getJDBCConnection() throws Exception{
Class.forName(className);
Connection connection = DriverManager.getConnection(url, user, password);
if(connection != null) {
return connection;
}
return null;
}
@Test
public void resultSetTest() throws Exception{
// 获取连接
Connection conn = getJDBCConnection();
if(conn != null){
// 待执行的SQL语句
String sql = "select job_id, job_title, min_salary, max_salary from jobs where min_salary > ? and max_salary < ?";
// 预编译
PreparedStatement preparedStatement = conn.prepareStatement(sql);
// 设置参数
preparedStatement.setInt(1,8000);
preparedStatement.setInt(2,20000);
// 执行SQL语句,获取结果集
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
// 获取一个对象的信息
String job_id = resultSet.getString("job_id");
String job_title = resultSet.getString(2);
int min_salary = resultSet.getInt("min_salary");
int max_salary = resultSet.getInt(4);
// 输出
System.out.println(job_id + " " + job_title + " " + min_salary + " " + max_salary) ;
}
// 关闭
conn.close();
preparedStatement.close();
resultSet.close();
}
}
@Test
public void resultSetExample1() throws Exception{
/*
查询薪资大于等于10000的所有员工的姓名first_name和last_name、电话号码phone_number和salary
*/
Connection conn = getJDBCConnection();
if(conn != null){
String sql = "SELECT first_name, last_name, phone_number, salary FROM employees WHERE salary >= ?";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
if(preparedStatement != null){
preparedStatement.setInt(1,10000);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet != null){
while (resultSet.next()){
String first_name = resultSet.getString("first_name");
String last_name =resultSet.getString("last_name");
String phone_number = resultSet.getString("phone_number");
int ansSalary = resultSet.getInt("salary");
System.out.println(first_name + "·" + last_name + " " + phone_number + " " + ansSalary);
}
resultSet.close();
preparedStatement.close();
conn.close();
}
}
}
}
@Test
public void resultSetExample2() throws Exception{
/*
随机生成(1~250)员工id(employee_id),若员工存在,则将该员工的薪资提高10%,并输出提高前和提高后的信息(fist_name,last_name,salary,email,phone_number),
否则,输出“No information about (此处补充输入的ID) was found in the database”
*/
Connection conn = getJDBCConnection();
if(conn != null){
// 待执行的SQL语句
String sql = "select * from employees where employee_id = ?";
PreparedStatement preparedStatement = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
if(preparedStatement != null){
int id = 100 + new Random().nextInt(151);
// System.out.println(id + "-------");
preparedStatement.setInt(1,id);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet != null){
while (resultSet.next()){
String first_name = resultSet.getString("first_name");
String last_name = resultSet.getString("last_name");
int salary = resultSet.getInt("salary");
String email = resultSet.getString("email");
String phone_number = resultSet.getString("phone_number");
System.out.println(first_name + " " + last_name + " " + salary + " " + email + " " + phone_number);
resultSet.updateInt("salary",salary + (int)((double)salary * 0.1));
resultSet.updateRow();
int salaryAfter = resultSet.getInt("salary");
System.out.println(first_name + " " + last_name + " " + salaryAfter + " " + email + " " + phone_number);
}
resultSet.close();
preparedStatement.close();
conn.close();
}else{
System.out.println("No information about " + id +" was found in the database");
preparedStatement.close();
conn.close();
}
}
}
}
@Test
public void test(){
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
// int i = 32;
System.out.println(i);
}
}