JAVA基础知识之JDBC——RowSet
RowSet概念
在C#中,提供了一个DataSet,可以把数据库的数据放在内存中进行离线操作(读写),操作完成之后再同步到数据库中去,Java中则提供了类似的功能RowSet.
RowSet接口继承自ResultSet接口。与ResultSet相比,RowSet默认是可滚动、可更新、可序列化的结果集,可以作为JavaBean来方便地在网络上传输,用于同步两端数据。对于离线RowSet而言,
程序从创建RowSet时就已经把数据load进内存,因此可以更好地利用内存性能,降低数据库服务器的负载,提高程序性能。
RowSet接口下包含了JdbcRowSet, CachedRowSet, FilteredRowSet, JoinRowSet, WebRowSet,除了JdbcRowSet之外,后面四个都是离线RowSet,它们之间的继承关系如下,
RowSetFactory
在JDK1.6及以前的版本中,如果要使用JdbcRowSet,则必须使用JdbcRowSetImpl的构造器来构造对象,但是在编译的时候会有警告,因此JdbcRowSetImpl是内部专用的API,在未来版本可能会删除。这种获取JdbcRowSet的方式是不推荐的,因为使用内部API,在将来的版本中可能不兼容,而且这样的程序直接与具体的实现类JdbcRowSetImpl耦合,不利于维护和升级。
在JDK1.7中,这个问题得到了改善。JDK1.7引入了RowSetFactory和RowSetProvider接口,其中RowSetProvider负责创建RowSetFactory,而RowSetFactory则可以通过以下方法创建RowSet实例,
- createCachedRowSet()
- createFilteredRowSet()
- createJdbcRowSet()
- createJoinRowSet()
- createWebRowSet()
通过RowSetFactory,程序就可以与RowSet的实现类分离,避免了直接使用具体的实现类JdbcRowSetImpl。
创建对象时可以传入ResultSet实例填充RowSet,也可以在创建JdbcRowSet实例之后通过execute(sql)方法得到数据填充RowSet,
下面演示使用RowSetFactory和RowSetProvider接口获取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.SQLException; 9 import java.util.Properties; 10 11 import javax.sql.rowset.JdbcRowSet; 12 import javax.sql.rowset.RowSetFactory; 13 import javax.sql.rowset.RowSetProvider; 14 15 16 public class RowSetFactoryTest { 17 private String driver; 18 private String url; 19 private String user; 20 private String pass; 21 public void initParam(String paramFile) throws FileNotFoundException, IOException, ClassNotFoundException { 22 //用Properties类加载属性文件 23 Properties prop = new Properties(); 24 prop.load(new FileInputStream(paramFile)); 25 driver = prop.getProperty("driver"); 26 url = prop.getProperty("url"); 27 user = prop.getProperty("user"); 28 pass = prop.getProperty("pass"); 29 Class.forName(driver); 30 } 31 32 public void update(String sql) throws SQLException { 33 RowSetFactory factory = RowSetProvider.newFactory(); 34 35 try ( 36 //使用RowSet的execute方式返回数据,则不再需DriverManager连接数据库了 37 //Connection conn = DriverManager.getConnection(url, user, pass); 38 /* 39 * for JDK1.6 40 * JdbcRowSet jdbcRs = new JdbcRowSetImpl(conn); 41 */ 42 // for JDK 1.7 43 JdbcRowSet jdbcRs = factory.createJdbcRowSet(); 44 ) { 45 jdbcRs.setUrl(url); 46 jdbcRs.setUsername(user); 47 jdbcRs.setPassword(pass); 48 jdbcRs.setCommand(sql); 49 jdbcRs.execute(); 50 51 jdbcRs.afterLast(); 52 //向前滚动结果集 53 while(jdbcRs.previous()) { 54 System.out.println(jdbcRs.getInt(1)+"\t"+jdbcRs.getString(2)+"\t"+jdbcRs.getString(3)); 55 56 if (jdbcRs.getInt("jdbc_id") == 3) { 57 //修改指定行记录,因为 JdbcRowSet 继承自 ResultSet, 所以修改记录的方式也一样 58 jdbcRs.updateString("jdbc_name", "小明"); 59 jdbcRs.updateRow(); 60 System.out.println("修改成功: "); 61 System.out.println(+jdbcRs.getInt(1)+"\t"+jdbcRs.getString(2)+"\t"+jdbcRs.getString(3)); 62 } 63 64 } 65 } 66 } 67 68 public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException { 69 RowSetFactoryTest jt = new RowSetFactoryTest(); 70 jt.initParam("mysql.ini"); 71 jt.update("select * from jdbc_test"); 72 } 73 }
执行上面程序会发现第3行被修改了,需要注意的是JdbcRowSet并不是离线的RowSet,因此需要在数据库保持连接的情况下才能修改数据
因为JdbcRowSet接口继承自ResultSet,所以修改数据的方法跟ResultSet一样的。 程序执行结果如下,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 修改成功: 27 3 小明 小强 28 2 学生名2 学生名3 29 1 学生名1 学生名2