离线RowSet
如果直接使用ResultSet, 程序在得到ResultSet记录之后需要立即使用,否则一旦关闭Connection就不再可用,要解决这种情况要么将ResultSet的结果转换成JavaBean存储,要么在Connection关闭之前完成所有操作,不过这些办法都不太方便。
但是通过离线的RowSet却能很好地解决这个问题。RowSet可以将ResultSet的结果集封装成RowSet对象,存储在内存中进行数据操作,而Connection则可以断开。直到数据操作完成之后,重新再连接数据库,进行数据同步即可。下面以CachedRowSet为例演示离线RowSet的用法,
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.ResultSet; 9 import java.sql.SQLException; 10 import java.sql.Statement; 11 import java.util.Properties; 12 13 import javax.sql.rowset.CachedRowSet; 14 import javax.sql.rowset.RowSetFactory; 15 import javax.sql.rowset.RowSetProvider; 16 17 public class CachedRowSetTest { 18 private static String driver; 19 private static String url; 20 private static String user; 21 private static String pass; 22 public void initParam(String paramFile) throws FileNotFoundException, IOException, ClassNotFoundException { 23 //用Properties类加载属性文件 24 Properties prop = new Properties(); 25 prop.load(new FileInputStream(paramFile)); 26 driver = prop.getProperty("driver"); 27 url = prop.getProperty("url"); 28 user = prop.getProperty("user"); 29 pass = prop.getProperty("pass"); 30 Class.forName(driver); 31 } 32 public CachedRowSet query(String sql) throws SQLException { 33 Connection conn = DriverManager.getConnection(url,user,pass); 34 Statement stmt = conn.createStatement(); 35 ResultSet rs = stmt.executeQuery(sql); 36 RowSetFactory factory = RowSetProvider.newFactory(); 37 CachedRowSet cachedRs = factory.createCachedRowSet(); 38 //使用ResultSet装填RowSet 39 cachedRs.populate(rs); 40 rs.close(); 41 stmt.close(); 42 conn.close(); 43 return cachedRs; 44 } 45 public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException { 46 CachedRowSetTest ct = new CachedRowSetTest(); 47 ct.initParam("mysql.ini"); 48 CachedRowSet rs = ct.query("select * from jdbc_test"); 49 rs.afterLast(); 50 while (rs.previous()) { 51 System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getString(3)); 52 if (rs.getInt(1) == 3) { 53 rs.updateString(3,"小强"); 54 rs.updateRow(); 55 } 56 } 57 //重新后去数据库连接 58 Connection conn = DriverManager.getConnection(url,user,pass); 59 conn.setAutoCommit(false); 60 rs.acceptChanges(conn); 61 } 62 }
程序执行结果,
1 27 学生名27 学生名28 2 26 学生名26 学生名27 3 25 学生名25 学生名26 4 24 学生名24 学生名25 5 23 学生名23 学生名24 6 22 学生名22 学生名23 7 21 学生名21 学生名22 8 20 学生名20 学生名21 9 19 学生名19 学生名20 10 18 学生名18 学生名19 11 17 学生名17 学生名18 12 16 学生名16 学生名17 13 15 学生名15 学生名16 14 14 学生名14 学生名15 15 13 学生名13 学生名14 16 12 学生名12 学生名13 17 11 学生名11 学生名12 18 10 学生名10 学生名11 19 9 学生名9 学生名10 20 8 学生名8 学生名9 21 7 学生名7 学生名8 22 6 学生名6 学生名7 23 5 学生名5 学生名6 24 4 学生名4 学生名5 25 3 小明 小强 26 2 学生名2 学生名3 27 1 学生名1 学生名2
离线RowSet查询分页
所谓分页,就是一次只装载ResultSet的某几条记录,这样可以避免CachedRowSet内存占用过大的问题。
CachedRowSet有如下方法控制分页,
populate(ResultSet rs, int startRow) , 从第startRow行开始装载
setPageSize(int pageSize), 设置每页大小
previousPage(); 在底层ResultSet可用情况下,让CachedRowSet读取上一页记录
nextPage() 在底层ResultSet可用情况下,让CachedRowSet读取下一页记录
下面演示CachedRowSet分页用法,
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.ResultSet; 9 import java.sql.SQLException; 10 import java.sql.Statement; 11 import java.util.Properties; 12 13 import javax.sql.rowset.CachedRowSet; 14 import javax.sql.rowset.RowSetFactory; 15 import javax.sql.rowset.RowSetProvider; 16 17 public class CachedRowSetPage { 18 private String driver; 19 private String url; 20 private String user; 21 private String pass; 22 public void initParam(String paramFile) throws FileNotFoundException, IOException, ClassNotFoundException { 23 //用Properties类加载属性文件 24 Properties prop = new Properties(); 25 prop.load(new FileInputStream(paramFile)); 26 driver = prop.getProperty("driver"); 27 url = prop.getProperty("url"); 28 user = prop.getProperty("user"); 29 pass = prop.getProperty("pass"); 30 Class.forName(driver); 31 } 32 33 public CachedRowSet query(String sql, int pageSize, int page) 34 throws SQLException { 35 try ( 36 Connection conn = DriverManager.getConnection(url, user, pass); 37 Statement stmt = conn.createStatement(); 38 ResultSet rs = stmt.executeQuery(sql) 39 ) { 40 RowSetFactory factory = RowSetProvider.newFactory(); 41 CachedRowSet cachedRs = factory.createCachedRowSet(); 42 // 设置pagesize 43 cachedRs.setPageSize(pageSize); 44 // 使用ResultSet装填RowSet, 设置从第几条记录开始 45 cachedRs.populate(rs, (page - 1) * pageSize + 1); 46 return cachedRs; 47 } 48 } 49 public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException { 50 CachedRowSetPage cp = new CachedRowSetPage(); 51 cp.initParam("mysql.ini"); 52 //设置每页显示3条记录, 读取第2页的记录 53 CachedRowSet rs = cp.query("select * from jdbc_test", 3, 2); 54 rs.afterLast(); 55 while (rs.previous()) { 56 System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getString(3)); 57 } 58 } 59 }
执行结果,只显示了第2页的数据
1 6 学生名6 学生名7 2 5 学生名5 学生名6 3 4 学生名4 学生名5