前面的ResultSetHandler的handler方法需要处理ResultSet,ResultSet保存的数据类似于二维数组的形式,每一行都是一条记录,那么要处理ResultSet就必须从每一行进行处理,这就是RowProcessor 的用处。
1.RowProcessor 行处理器
public interface RowProcessor {
//将ResultSet的第一行转化为Object数组的形式
Object[] toArray(ResultSet rs) throws SQLException;
//将ResultSet的第一行转化为Bean对象,只处理一行数据
<T> T toBean(ResultSet rs, Class<? extends T> type) throws SQLException;
//将ResultSet的所有行转化为Bean对象列表,处理的是完整的ResultSet数据
<T> List<T> toBeanList(ResultSet rs, Class<? extends T> type) throws SQLException;
//将ResultSet的第一行转化为Map对象,只处理一行数据,优先以列的别名作为key,其次是实际的列名
Map<String, Object> toMap(ResultSet rs) throws SQLException;
}
2.BasicRowProcessor dbutils只提供了一个行处理器的实现类
public class BasicRowProcessor implements RowProcessor {
//bean处理器,用于组装bean对象的
private static final BeanProcessor defaultConvert = new BeanProcessor();
private static final BasicRowProcessor instance = new BasicRowProcessor();
//单例模式创建实例,底下也提供构造函数来实例化处理器
@Deprecated
public static BasicRowProcessor instance() {
return instance;
}
private final BeanProcessor convert;
public BasicRowProcessor() {
//使用默认的Bean处理器
this(defaultConvert);
}
//指定bean处理器
public BasicRowProcessor(BeanProcessor convert) {
super();
this.convert = convert;
}
//将第一数据封装为Object数组返回
@Override
public Object[] toArray(ResultSet rs) throws SQLException {
//获取ResultSet的元数据信息
ResultSetMetaData meta = rs.getMetaData();
//获取列数
int cols = meta.getColumnCount();
Object[] result = new Object[cols];
//直接遍历赋值返回结束
for (int i = 0; i < cols; i++) {
result[i] = rs.getObject(i + 1);
}
return result;
}
//这里又调用Bean处理器去处理了,各个类的职责层次感很强分的很有逻辑,这里也是只处理第一行的数据
@Override
public <T> T toBean(ResultSet rs, Class<? extends T> type) throws SQLException {
return this.convert.toBean(rs, type);
}
//同上,只是处理所有行的记录了,返回的bean列表
@Override
public <T> List<T> toBeanList(ResultSet rs, Class<? extends T> type) throws SQLException {
return this.convert.toBeanList(rs, type);
}
//将第一行的数据封装成Map对象,key优先判断是否有别名,没有才有数据库列名,
@Override
public Map<String, Object> toMap(ResultSet rs) throws SQLException {
//实例化内部静态类,用于处理大小写不敏感,name和Name取得同一对象
Map<String, Object> result = new CaseInsensitiveHashMap();
ResultSetMetaData rsmd = rs.getMetaData();
//获取结果集列数
int cols = rsmd.getColumnCount();
for (int i = 1; i <= cols; i++) {
//优先取列的别名
String columnName = rsmd.getColumnLabel(i);
//别名不存在取数据库中字段名
if (null == columnName || 0 == columnName.length()) {
columnName = rsmd.getColumnName(i);
}
result.put(columnName, rs.getObject(i));
}
return result;
}
private static class CaseInsensitiveHashMap extends LinkedHashMap<String, Object> {
//保存键的大小写对应关系,例如 name=NAME, id=ID, age=age; 键一定是小写,值根据put决定
private final Map<String, String> lowerCaseMap = new HashMap<String, String>();
private static final long serialVersionUID = -2848100435296897392L;
@Override
public boolean containsKey(Object key) {
//一律将key转为小写查询,获得真实的列名
Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
//判断是否存在
return super.containsKey(realKey);
// Possible optimisation here:
// Since the lowerCaseMap contains a mapping for all the keys,
// we could just do this:
// return lowerCaseMap.containsKey(key.toString().toLowerCase());
}
@Override
public Object get(Object key) {
Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
return super.get(realKey);
}
@Override
public Object put(String key, Object value) {
//为了保持lowerCaseMap 的同步,先remove再put
Object oldKey = lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key);
Object oldValue = super.remove(oldKey);
super.put(key, value);
return oldValue;
}
@Override
public void putAll(Map<? extends String, ?> m) {
for (Map.Entry<? extends String, ?> entry : m.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
this.put(key, value);
}
}
@Override
public Object remove(Object key) {
Object realKey = lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH));
return super.remove(realKey);
}
}
}