八、JDBC——4-RowSet
4-RowSet
(1)RowSet接口继承了ResultSet接口,RowSet接口下包含JdbcRowSet、CachedRowSet、FilteredRowSet、JoinRowSet和WebRowSet常用子接口。其中除了JdbcRowSet需要保持与数据库的连接以外,其余都是离线的RowSet,无须保持与数据库的连接;
(2)与ResultSet相比,RowSet默认是可滚动、可更新、可序列化的结果集,而且可以作为JavaBean使用,因此能方便的在网络上传输,用于同步两端的数据。程序在创建RowSet时已经把数据从底层数据库读取到了内存,可以充分利用计算机的内存,降低数据库服务器的负载,提高程序性能;
1.RowSetFactory和RowSet
(1)RowSetFactory用于创建RowSet实例;
(2)创建RowSet:
import javax.sql.rowset.JdbcRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider; public class CreateRowSet { public static void main(String[] args)throws Exception { Class.forName("com.mysql.jdbc.Driver"); //加载数据库驱动 //使用RowSetProvider创建RowSetFactory RowSetFactory factory = RowSetProvider.newFactory(); //使用RowSetFactory创建默认的JdbcRowSet JdbcRowSet jrs = factory.createJdbcRowSet(); //设置必要的连接信息 jrs.setUrl("jdbc:mysql://localhost/test"); //url jrs.setUsername("root"); //user jrs.setPassword("stx12345"); //pass //设置SQL语句 jrs.setCommand("select * from test2"); //执行查询 jrs.execute(); while(jrs.next()){ System.out.println(jrs.getInt(1)+"|"+jrs.getString(2)+"|"+jrs.getInt(3)); } } }
2.离线RowSet
(1)对传统的ResultSet有两种处理方式:
1)ResultSet->JavaBean,完成转换后关闭连接等资源;
2)Connection一直处于连接状态,直接将ResultSet传到视图层;
(2)离线RowSet会直接将底层数据读入内存中(之后可以关闭Connection),封装成RowSet对象,RowSet对象可以直接当做JavaBean使用,不仅安全,编程简单;
(3)离线RowSet使用:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider; public class RowSetTest { public CachedRowSet query(String sql)throws Exception{ //加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "stx12345"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery(sql); //使用RowSetProvider创建RowSetFactory RowSetFactory factory = RowSetProvider.newFactory(); //使用RowSetFactory创建CachedRowSet CachedRowSet crs = factory.createCachedRowSet(); //使用ResultSet装填RowSet crs.populate(rs); //关闭资源 rs.close(); stat.close(); conn.close(); return crs; } public static void main(String[] args)throws Exception { RowSetTest test = new RowSetTest(); CachedRowSet crs = test.query("select * from test2"); crs.afterLast(); //向前滚动结果集 while(crs.previous()){ System.out.println(crs.getInt(1)+"|"+crs.getString(2)+"|"+crs.getInt(3)); if(crs.getInt("id")==3){ //修改指定行记录 crs.updateString(2, "hahaha"); crs.updateRow(); } } //重新获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "stx12345"); conn.setAutoCommit(false); //把对RowSet所做修改同步到底层数据库 crs.acceptChanges(conn); } }
3.离线RowSet的分页查询
(1)由于RowSet会把数据记录直接装载到内存中,如果SQL查询返回的记录过大,RowSet将会占用大量的内存,极有可能会导致内存溢出;为了解决此问题,RowSet提供了分页功能(即一次只装载ResultSet中的某几条记录),这样就可以避免占用内存过大;
(2)离线RowSet的分页查询:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider; public class RowSetTest2 { public CachedRowSet query(String sql)throws Exception{ //加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "stx12345"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery(sql); //使用RowSetProvider创建RowSetFactory RowSetFactory factory = RowSetProvider.newFactory(); //使用RowSetFactory创建CachedRowSet CachedRowSet crs = factory.createCachedRowSet(); //设置每页显示两条记录 crs.setPageSize(2); //使用ResultSet装填RowSet,从第一条开始记录 crs.populate(rs,1); //关闭资源 rs.close(); stat.close(); conn.close(); return crs; } public static void main(String[] args)throws Exception { RowSetTest2 test = new RowSetTest2(); //使用RowSetProvider创建RowSetFactory CachedRowSet crs = test.query("select * from test2"); while(crs.next()){ System.out.println(crs.getInt(1)+"|"+crs.getString(2)+"|"+crs.getInt(3)); if(crs.getInt("id")==3){ //修改指定行记录 crs.updateString(2, "hahaha"); crs.updateRow(); } } } }