功能:
- 添加了JavaBeans组件支持
- 让JDBC使用起来更加简单,操作更加丰富
知识点摘要:
- RowSet继承自ResultSet,添加了JavaBeans组件支持
- 5个子接口:(具体见扩展阅读)
JdbcRowSet
CachedRowSet
WebRowSet
JoinRowSet
FilteredRowSet - 优点:
1.某些子接口支持离线操作(可断开数据库连接)
2.可当作JavaBeans使用,可序列化(方便网络传输)
本文摘要:
- java7前RowSet的使用(比常规的5步使用jdbc简单很多)
- java7后RowSet的使用(更简单)
- 演示离线的RowSet
- 离线的RowSet操作
- RowSet的分页
说明:
- Java使用DatabaseMetaData来获取数据库相关信息
- 本文为了代码结构清晰 采用的是try-with-resource结构,请在java7下使用(或者自己改成传统模式)
- 想了解更多请看:官方RowSet使用说明(2013-03-03有效)
部分API:
返回类型 | 方法名称 | 说明 |
---|---|---|
String | getDatabaseProductName() | 获得数据库产品的名称 |
String | getDatabaseProductVersion() | 获得数据库产品的版本 |
String | getDriverVersion() | 获得JDBC驱动的版本号 |
String | getURL() | 获得当前数据连接的URL |
boolean | isReadOnly() | 当前数据连接的数据库是否是只读模式 |
boolean | supportsBatchUpdates() | 数据库是否支持批量操作 |
boolean | supportsResultSetType(int type) | 数据库是否支持给定结果集类型 |
ResultSet | getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) | 简单的讲就是获得数据表的相关信息 |
ResultSet | getPrimaryKeys(String catalog, String schema, String table) | 获得某表的主键 |
ResultSet | getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) | 获得某表字段信息 |
程序演示: 放大
- package com.cxy.jdbc;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.UUID;
- import javax.sql.rowset.CachedRowSet;
- import javax.sql.rowset.JdbcRowSet;
- import javax.sql.rowset.RowSetFactory;
- import javax.sql.rowset.RowSetProvider;
- import com.sun.rowset.JdbcRowSetImpl;
- /**
- * @author cxy @ www.cxyapi.com
- */
- public class RowSetTest
- {
- public static void main(String[] args) throws Exception
- {
- Class.forName("com.mysql.jdbc.Driver");
- //java7前的使用方法,是不是看起来简单很多~
- try
- (
- Connection con=DriverManager.getConnection("jdbc:mysql://localhost/dbtest", "root", "root");
- JdbcRowSet jrs=new JdbcRowSetImpl(con); //传递一个con给JdbcRowSet构造器就可以啦
- )
- {
- jrs.setCommand("select * from t_student");
- jrs.execute();
- System.out.println("id\t姓名\t 性别");
- while(jrs.next())
- {
- System.out.println(jrs.getString(1)+"\t"+jrs.getString(2)+"\t"+jrs.getString(3));
- }
- }
- System.out.println("=======================");
- //java7开始 提供了RowSetFactory接口来生成各种RowSet
- RowSetFactory rsf=RowSetProvider.newFactory();
- try
- (
- JdbcRowSet jrs=rsf.createJdbcRowSet();
- )
- {
- jrs.setUrl("jdbc:mysql://localhost/dbtest");
- jrs.setUsername("root");
- jrs.setPassword("root");
- jrs.setCommand("select * from t_student");
- jrs.execute();
- System.out.println("id\t姓名\t 性别");
- while(jrs.next())
- {
- System.out.println(jrs.getString(1)+"\t"+jrs.getString(2)+"\t"+jrs.getString(3));
- }
- }
- System.out.println("=======================");
- //是不是更简单了呢?我认为还是极好的~ 至少我只知道JdbcRowSet就可以进行数据库操作了,不像原来要创建各种对象
- //如果RowSet没有提供一个con的话,那么他将使用RowSetReader来完成execute方法
- //下面 我们来看一个离线版的RowSet,关闭数据库连接后仍然能使用的RowSet
- try
- (
- //由于JdbcRowSet是非离线的 所以 这里我们更换成一个离线的RowSet:CachedRowSet
- Connection con=DriverManager.getConnection("jdbc:mysql://localhost/dbtest", "root", "root");
- PreparedStatement pstmt=con.prepareStatement("select * from t_student",
- ResultSet.TYPE_SCROLL_SENSITIVE,
- ResultSet.CONCUR_UPDATABLE);
- ResultSet rs=pstmt.executeQuery();
- CachedRowSet crs=rsf.createCachedRowSet();
- )
- {
- crs.populate(rs); //封装rs成CachedRowSet
- con.close(); //好了 我们将con这个关闭
- try
- {
- while(rs.next())
- {
- System.out.println(rs.getString(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3));
- }
- }catch(Exception e)
- {
- System.out.println("由于con已经关闭,rs不能再被访问");
- }
- System.out.println("但是离线的crs仍可访问");
- System.out.println("id\t姓名\t 性别");
- while(crs.next())
- {
- System.out.println(crs.getString(1)+"\t"+crs.getString(2)+"\t"+crs.getString(3));
- }
- }
- System.out.println("=======================");
- //演示如果操作数据(这里演示的是如何插入数据)
- CachedRowSet crs1=rsf.createCachedRowSet();
- crs1.setUrl("jdbc:mysql://localhost/dbtest");
- crs1.setUsername("root");
- crs1.setPassword("root");
- crs1.setCommand("select * from t_student");
- crs1.execute();
- //这样的操作只能改变离线的RowSet
- crs1.moveToInsertRow(); //将指针移动到插入行,当前的位置将会被记住
- crs1.updateString(1, UUID.randomUUID().toString().replace("-", ""));
- crs1.updateString(2, "克隆人"+System.currentTimeMillis());
- crs1.updateString(3, "女");
- crs1.insertRow(); //必须和moveToInsertRow联合使用
- crs1.moveToCurrentRow(); //做完插入操作后,将指针指回到插入状态前的行
- crs1.beforeFirst();
- while(crs1.next())
- {
- System.out.println(crs1.getString(1)+","+crs1.getString(2)+","+crs1.getString(3));
- }
- //如果想同步数据库那么就需要重新连接数据库,然后把数据提交上去
- try
- (
- Connection con=DriverManager.getConnection("jdbc:mysql://localhost/dbtest", "root", "root");
- )
- {
- con.setAutoCommit(false); //这句必须要否则会造成下面那句的异常
- crs1.acceptChanges(con); //同步数据到数据库
- }
- System.out.println("=======================");
- //最后我们来看看分页
- /* 第一种方式 有ResultSet的
- * crs.setPageSize(pageSize); //设置每页的大小
- * crs.populate(rs, (page-1)*pageSize+1); //封装rs从第几行(根据页和每页大小算出)开始
- * 个人觉得这种方式不好,因为 这个实际上还是先查出了所有结果rs,然后再同java的方式截取出咱们想要的那页数据
- * */
- crs1.setPageSize(3); //每页显示几条
- crs1.execute();
- System.out.println(crs1.isBeforeFirst());
- int i=1;
- System.out.println("第"+i+"页:");
- while(crs1.next())
- {
- System.out.println(crs1.getString(1)+","+crs1.getString(2)+","+crs1.getString(3));
- }
- i++;
- while(crs1.nextPage())
- {
- System.out.println("第"+i+"页:");
- while(crs1.next())
- {
- System.out.println(crs1.getString(1)+","+crs1.getString(2)+","+crs1.getString(3));
- }
- i++;
- }
- }
- }
转载请加本站连接: www.cxyapi.com
扩展阅读:
转载于:https://blog.51cto.com/congwa/1163843
1.RowSet 5个常用子接口介绍
JdbcRowSet:封装ResultSet,使得它能可以当作JavaBeans使用,但是它必须保持与数据库的连接(非离线)。CachedRowSet:拥有JdbcRowSet所有功能,同时还能断开数据库连接进行离线操作。
WebRowSet:拥有所有的CachedRowSet功能,同时还能通过xml来描述自己(把自己写成xml,通过xml来配置自己)。
JoinRowSet:拥有所有WebRowSet的功能,同时它能在断开数据源的情况下做一个sql join(感觉就是java版的表连接,比如2个结果集 我通过什么字段将其关联成一个表,sql中的join(联表)操作)。
FilteredRowSet:有所有哦的WebRowSet的功能,如其名,可以做过滤操作(在不使用查询语句和断开数据源的情况下)。
2.RowSet离线接口解决的问题
过去使用ResultSet的方式:方式1:将结果集遍历,封装成List<Map<String,Object>>,然后关闭数据库连接,使用这个封装好的对象(最常用的形式)
方式2:再遍历使用ResultSet的过程,数据库连接一直处于打开状态,操作完毕后才关闭数据库连接(简单程序和初学者都这么干)
分析:方式1就是有一次转换的过程,无形中造成了性能的浪费,方式2的数据库连接一直处于打开状态,性能低且不安全。
RowSet有很多可离线的子接口,解决了上面两种方式的所有问题,想必这是极好的~
3.关于分页的一些说明
1.crs.previousPage();可以向前翻页。2.每次nextPage都会创建一个新的CachedRowSet,每次只有PageSize条数据在内存中(官方解释 )。
4.关于没有con的execute();执行说明
如果RowSet不是通过Connection一步一步得到的,那么它的执行是通过RowSetReader完成的。详解 待续...