本文内容主要是对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表格等等),还是可以了解一般