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)+"\t"+rs.getString(2)+"\t"+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