ResultSet不仅可以内存中的一张二维表一样保存statement执行SQL的结果集,还能通过结果集修改DB的数据。ResultSetMetaData则可以用来获得ResultSet对象的相关信息。
ResultSet支持滚动和并发,但需要在创建statement时候,额外传入参数
可滚动结果集
ResultSet用来定位行的方法有,next(), last(), absolute(), previous(), afterLast()等等。
支持absolute(), previous(), afterLast()等方法的结果集,称为可滚动结果集。在创建PreparedStatement时,可以通过传入ResultSetType参数来支持可滚动结果集,
ResultSetType支持三种取值,
- ResultSet.TYPE_FORWARD_ONLY, 只能向前移动(JDK1.4以前的默认值)
- ResultSet.TYPE_SCROLL_INSENSITIVE, 可滚动,但是底层数据的改变不会影响结果集
- ResultSet.TYPE_SCROLL_SENSITIVE, 可滚动,底层数据的改变会影响结果集
支持并发结果集
在创建statement时,传入resultSetConcurrency(即并发类型)可以控制结果集的并发性,resultSetConcurrency有两种取值
- ResultSet.CONCUR_READ_ONLY,只读的并发模式(默认)
- ResultSet.CONCUR_UPDATABLE,可更新的并发模式
另外,可更新的结果集还需要满足两个条件,
- 所有数据都来自一个表;
- 选出的数据集必须包含主键列
要通过结果集更新数据库,只需要调用ResultSet对象的updateXxx(index, value)方法修改和updateRow()方法提交即可。
对于支持以上两种特性的结果集,在创建statement时可以这么创建,
1 PreparedStatement pstmt = conn.prepareStatement(sql 2 , ResultSet.TYPE_SCROLL_INSENSITIVE 3 , ResultSet.CONCUR_UPDATABLE);
下面演示ResultSet的滚动和更新
1 package db; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.sql.Connection; 7 import java.sql.DriverManager; 8 import java.sql.PreparedStatement; 9 import java.sql.ResultSet; 10 import java.sql.SQLException; 11 import java.util.Properties; 12 13 public class ResultSetTest { 14 private String driver; 15 private String url; 16 private String user; 17 private String pass; 18 public void initParam(String paramFile) throws FileNotFoundException, IOException, ClassNotFoundException { 19 //用Properties类加载属性文件 20 Properties prop = new Properties(); 21 prop.load(new FileInputStream(paramFile)); 22 driver = prop.getProperty("driver"); 23 url = prop.getProperty("url"); 24 user = prop.getProperty("user"); 25 pass = prop.getProperty("pass"); 26 Class.forName(driver); 27 } 28 29 public void query(String sql) throws SQLException { 30 try ( 31 Connection conn = DriverManager.getConnection(url, user, pass); 32 //创建prepareStatement可以传入额外参数,用来控制结果集是否支持滚动和更新 33 //传入两个额外参数,即ResultSet中的两个常量 34 //TYPE_SCROLL_INSENSITIVE表示结果集可滚动,但底层数据改变不会影响ResultSet的内容 35 //CONCUR_UPDATABLE支持ResultSet可更新的并发模式 36 PreparedStatement pstmt = conn.prepareStatement(sql 37 , ResultSet.TYPE_SCROLL_INSENSITIVE 38 , ResultSet.CONCUR_UPDATABLE); 39 ResultSet rs = pstmt.executeQuery() ) { 40 rs.last(); 41 int rowCount = rs.getRow(); 42 for (int i = rowCount; i > 0 ; i--) { 43 rs.absolute(i); 44 System.out.println("打印第 "+i+" 行: "+rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)); 45 //修改当前行,第2列和第3列的值 46 rs.updateString(2, "学生名"+i); 47 rs.updateString(3, "学生名"+(i+1)); 48 //提交修改 49 rs.updateRow(); 50 } 51 } 52 } 53 54 public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException { 55 ResultSetTest rt = new ResultSetTest(); 56 rt.initParam("mysql.ini"); 57 rt.query("select * from jdbc_test"); 58 } 59 }
执行结果如下,
1 打印第 27 行: 27 学生名27 学生名28 2 打印第 26 行: 26 学生名26 学生名27 3 打印第 25 行: 25 学生名25 学生名26 4 打印第 24 行: 24 学生名24 学生名25 5 打印第 23 行: 23 学生名23 学生名24 6 打印第 22 行: 22 学生名22 学生名23 7 打印第 21 行: 21 学生名21 学生名22 8 打印第 20 行: 20 学生名20 学生名21 9 打印第 19 行: 19 学生名19 学生名20 10 打印第 18 行: 18 学生名18 学生名19 11 打印第 17 行: 17 学生名17 学生名18 12 打印第 16 行: 16 学生名16 学生名17 13 打印第 15 行: 15 学生名15 学生名16 14 打印第 14 行: 14 学生名14 学生名15 15 打印第 13 行: 13 学生名13 学生名14 16 打印第 12 行: 12 学生名12 学生名13 17 打印第 11 行: 11 学生名11 学生名12 18 打印第 10 行: 10 学生名10 学生名11 19 打印第 9 行: 9 学生名9 学生名10 20 打印第 8 行: 8 学生名8 学生名9 21 打印第 7 行: 7 学生名7 学生名8 22 打印第 6 行: 6 学生名6 学生名7 23 打印第 5 行: 5 学生名5 学生名6 24 打印第 4 行: 4 学生名4 学生名5 25 打印第 3 行: 3 学生名3 学生名4 26 打印第 2 行: 2 学生名2 学生名3 27 打印第 1 行: 1 学生名1 学生名2