一个可以重复遍历的RowSet
本文内容主要是对com.sun.rowset.CachedRowSetImpl工具类的使用样例
这里复习一下JBDC数据库查询
PreparedStatement pstmt = conn.prepareStatement(fsql);
ResultSet rs = pstmt.executeQuery();
这个ResultSet一般是只能遍历一次的,如果需要多次重复遍历一般会使用工具类com.sun.rowset.CachedRowSetImpl 将ResultSet的rs对象populate方法缓存,这样的花开只要每次beforeFirst下就可以重复遍历
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(rs);
crs.beforeFirst();
将ResultSet转换为List<Map<String,T>> 或者List<Bean>一般是使用以下方式
List<Map<String,Object>> listMap=new ArrayList<Map<String,Object>>();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
Map<String, Object> bean=null;while(rs.next()){bean=new HashMap<String, Object>();for (int i = 0; i <columnCount; i++) {bean.put(metaData.getColumnName(i+1), rs.getObject(i+1));}listMap.add(bean);
}
如果将List<Map<String,T>>转换为ResultSet呢? 网络上一般都是使以下方式创建多个列的结果集,大致原理步骤就是首先数据库使用sql创建多个字段先查询出一个没有记录数的结果集,且先转换为缓存的结果集,然后将列表数据根据不同列塞入
Strng fsql="SELECT '' AS COLUM_1,'' AS COLUM_2 FROM DUAL WHERE 1=2 ";
PreparedStatement pstmt = conn.prepareStatement(fsql);
ResultSet rs = pstmt.executeQuery();
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(rs);
crs.beforeFirst();List<Map<String,String>> listBean=new ArrayList<>();String[] colNames=new String[]{"CLOUM_1","CLOUM_2"};for (Map<String, String> bean : listBean) {rs.last();rs.moveToInsertRow();for (String columName : colNames) {rs.updateObject(columName,bean.get(columName));}rs.insertRow();rs.moveToCurrentRow();rs.beforeFirst();
}
以上方法虽然可以解决问题,,但是让我不能忍受的是(需要连接数据库,很烦),但对日常模拟测试,可优化为以下代码
public static <T> RowSet list2RowSet(List<Map<String, T>> listBean, Set<String> colNames) throws SQLException {if (listBean == null) {listBean = new ArrayList<Map<String, T>>();}if (colNames == null || colNames.isEmpty()) {throw new RuntimeException("行至少有一列");}CachedRowSetImpl rs = new CachedRowSetImpl();RowSetMetaData metaData = new RowSetMetaDataImpl();rs.setMetaData(metaData);metaData.setColumnCount(colNames.size());int columnIndex = 0;for (String columName : colNames) {metaData.setColumnName(++columnIndex, columName);metaData.setColumnLabel(columnIndex, columName);}for (Map<String, T> bean : listBean) {rs.last();rs.moveToInsertRow();for (String columName : colNames) {rs.updateObject(columName, bean.get(columName));}columnIndex = 0;rs.insertRow();rs.moveToCurrentRow();rs.beforeFirst();}return rs;}
测试方法
public static void main(String[] args) {try {List<Map<String, Object>> listBean = new ArrayList<Map<String, Object>>();for (int i = 0; i < 5; i++) {Map<String, Object> bean1 = new HashMap<String, Object>();bean1.put("USER_NAME", "邓霖涛_" + i);bean1.put("PASSWORD", Math.random());listBean.add(bean1);}Set<String> colNames = listBean.get(0).keySet();RowSet rs = list2RowSet(listBean, colNames);//打印输出while (rs.next()) {System.out.println(rs.getObject("USER_NAME"));System.out.println(rs.getObject("PASSWORD"));}} catch (SQLException e) {e.printStackTrace();}}
输出测试结果
总结:com.sun.rowset.CachedRowSetImpl 类简单来说就是一个实现了RowSet接口与的一个缓存实现,具体可以查看对于源码,可对内部所有元数据重新定义,数据插入等等, 对目前来说这个工具类好像没什么鸡毛用处,但对于老系统(十几年前的可能还是JDBC直接操作RowSet,前端组件都可能是使用RowSet进行遍历生成相应的UI表格等等),还是可以了解一般