读书人

Commons DbUtils 源码翻阅三

发布时间: 2012-12-27 10:17:10 作者: rapoo

Commons DbUtils 源码阅读三

? 前两天着实被javaeye关闭着急了一下,还好,总算开放了!

? 继续我们的DbUtils组件的阅读研究吧。

??RowProcessor的实现子类:BasicRowProcessor

????

/** * RowProcessor接口的实现类 */public class BasicRowProcessor implements RowProcessor {    /**     * 默认转换器     * 如果没有指定,则使用这个进行resultSet的转换     */    private static final BeanProcessor defaultConvert = new BeanProcessor();    private static final BasicRowProcessor instance = new BasicRowProcessor();    /**     * 返回BasicRowProcessor的单实例     * 过期方法,建议使用构造器创建对象,这个方法将在DbUtils 1.1中去掉     * @return 这个类的单实例.     * @deprecated     */    public static BasicRowProcessor instance() {        return instance;    }    /**     * 使用这个实例来进行bean的转换     */    private final BeanProcessor convert;    /**     * BasicRowProcessor构造器. * 默认使用BeanProcessor转换     */    public BasicRowProcessor() {        this(defaultConvert);    }        /**     * BasicRowProcessor构造器.     * @param convert 当需要将表属性名转换为bean属性时要使用的BeanProcessor实例     * @since DbUtils 1.1     */    public BasicRowProcessor(BeanProcessor convert) {        super();        this.convert = convert;    }    /**     * 将ResultSet的一行转换为一个Object[]数组     * 这个实现将ResultSet中的数据顺序的存入数组.     * 如果列值为NULL,则数组元素设置为null.     */    public Object[] toArray(ResultSet rs) throws SQLException {        ResultSetMetaData meta = rs.getMetaData();//获取ResultSet的MetaData对象        int cols = meta.getColumnCount();//获取列数        Object[] result = new Object[cols];        for (int i = 0; i < cols; i++) {            result[i] = rs.getObject(i + 1);//获取每列对应的值,并赋给新数组        }        return result;    }    /**     * 将ResultSet的指定行转换为一JavaBean. * 这个实现代理需要一个BeanProcessor实例.     * 具体的可参见:BeanProcessor的toBean(java.sql.ResultSet, java.lang.Class)方法     */    public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException {        return this.convert.toBean(rs, type);    }    /**     * 将ResultSet的指定行转换为一JavaBean集合.       * 该方法同样需要一个BeanProcessor实例      * 具体的可参见:BeanProcessor的toBeanList(java.sql.ResultSet, java.lang.Class)方法     */    public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException {        return this.convert.toBeanList(rs, type);    }    /**     * 将指定的ResultSet行转换为一个Map     * 这个实现返回一个以大小写无关的列名为键值的Map集合      * 例如:调用map.get("COL")或者map.get("col")返回相同的值.     */    public Map<String, Object> toMap(ResultSet rs) throws SQLException {        Map<String, Object> result = new CaseInsensitiveHashMap();//创建一个自定义的大小写无关的Map实例        ResultSetMetaData rsmd = rs.getMetaData();        int cols = rsmd.getColumnCount();        for (int i = 1; i <= cols; i++) {            result.put(rsmd.getColumnName(i), rs.getObject(i));//这一用法就是将列名为键值        }        return result;    }}

?

? BasicRowProcessor这个类实现了RowProcessor接口的ResultSet转换为其它对象的方法,现对这个类的几点具体说明如下:

????? 1)

??????

public Object[] toArray(ResultSet rs) throws SQLException 

??? 这个方法也实在是没啥好说的,一切尽在掌握,很直白,就是利用ResultSet的MetaData对象来对当前行进行数据的处理操作,最后存入一数组对象,所以,略过!

??? 2)

????

    public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException {        return this.convert.toBean(rs, type);    }    public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException {        return this.convert.toBeanList(rs, type);    }

??这两个方法之所以会要一起列出来,主要是出于以下几个原因的考虑,一点是,它们都需要一个BeanProcessor实例来对ResultSet进行处理;另一点则是,我不想把对这两个的分析放在这里,而是想考虑放到下一节:BeanProcessor的分析(对BeanProcessor的分析也会碰到一新东西,那就是Java的内省Introspector,挺有意思的一知识点,你,值得期待)。实际上呢,我们通过对BasicRowProcessor的分析,我们也可以知道,它默认是采用这个BeanProcessor来处理ResultSet的。

?????3)???????

public Map<String, Object> toMap(ResultSet rs) throws SQLException

?

???根据这个方法的注释说明,它根据列名获取值,是大小写无关的,实际上一般的Map不可能做到这一点,因为Java是个区分大小写的语言,所以,它肯定对Map进行了封装。实际上呢,这个类里面有个静态的内部类CaseInsensitiveHashMap,真正的奥秘就在这里!这里我把它移出来了,现对此Map的分析如下:

???

    /**     * 为了不区分大小写查找而将所有的key转换为小写字符串的Map.     * 这个HashMap的实现不允许键值为null,因为我们要将所有的键值变为小写,     * 即调用key.toString().toLowerCase().     */    private static class CaseInsensitiveHashMap extends HashMap<String, Object> {        /**         * 以小写字母为键值的内部Map集合         * 所有的查询操作步骤操作经过以下三步:         * 1)、将参数Key转换为小写         * 2)、获取小写Key获取真实Key             * 3)、通过真实的Key值获取到值         */        private final Map<String,String> lowerCaseMap = new HashMap<String,String>();        /**         * Required for serialization support.         *          * @see java.io.Serializable         */         private static final long serialVersionUID = -2848100435296897392L;        @Override        public boolean containsKey(Object key) {            Object realKey = lowerCaseMap.get(key.toString().toLowerCase());            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());//获取真正的Key值,然后回去值            return super.get(realKey);        }        @Override        public Object put(String key, Object value) {            /*             * In order to keep the map and lowerCaseMap synchronized,             * we have to remove the old mapping before putting the              * new one. Indeed, oldKey and key are not necessaliry equals.             * (That's why we call super.remove(oldKey) and not just             * super.put(key, value))             */            Object oldKey = lowerCaseMap.put(key.toLowerCase(), key);//返回之前存在的值,实际上对应的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());//返回该键对应的值            //实际上我们可以理解为拿到真正的Key值,然后删除对应的值            return super.remove(realKey);        }    }

??? 很一目了然了已经,通过成员变量lowerCaseMap来达到大小写通吃的目的,这个lowerCaseMap,Key值为小写化的列名,Value值才对应真实列名(即未做最小化处理的列名)。所以说,每次在以列名获取值时,先对其进行最小化,再通过lowerCaseMap获取对应的真实列名,然后再获取到值,这样就达到了一个不区分大小写的效果。OK,这个Map转换总算整明白了。这样呢,我们对这个BasicRowProcessor类的解读也算是圆满完成了。

??

?

?

?

?

读书人网 >其他数据库

热点推荐