阅读 dbutils 源码(三)

阅读 dbutils 源码(三)

BeanProcessor 类

这个类主要是辅助RowProcessor这个接口的实现类,例如BasicRowProcessor中就默认使用BeanProcessor,当然也可以自己重写一个BeanProcessor,然后作为参数在BasicRowProcessor构造函数中传进去即可。

先看一下BeanProcessor中的方法:
这里写图片描述
其中toBeantoBeanList这两个方法比较重要,上一篇博客也提到过,在BasicRowProcessor就是调用的这两个方法,将结果集转成对应的bean或bean集合。

toBean 的实现

toBean方法:

    public <T> T toBean(final ResultSet rs, final Class<? extends T> type) throws SQLException {
        //反射创建一个对象
        final T bean = this.newInstance(type);
        //将结果集映射到对象
        return this.populateBean(rs, bean);
    }

populateBean方法:

    public <T> T populateBean(final ResultSet rs, final T bean) throws SQLException {
        //PropertyDescriptor是对javabean属性的描述,可以据此获取属性的名称、类型、set/get方法等,前提是必须是符合标准的javabean,必须有set/get方法,boolean类型的可以用is代替get。
        final PropertyDescriptor[] props = this.propertyDescriptors(bean.getClass());
        final ResultSetMetaData rsmd = rs.getMetaData();
        //列与属性序号对应
        final int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
        //给bean赋值
        return populateBean(rs, bean, props, columnToProperty);
    }
    private <T> T populateBean(final ResultSet rs, final T bean,
                               final PropertyDescriptor[] props, final int[] columnToProperty)
            throws SQLException {
        for (int i = 1; i < columnToProperty.length; i++) {
            //列没有对应的属性
            if (columnToProperty[i] == PROPERTY_NOT_FOUND) {
                continue;
            }
            //找到列对应的属性描述
            final PropertyDescriptor prop = props[columnToProperty[i]];
            //属性类型
            final Class<?> propType = prop.getPropertyType();
            Object value = null;
            if (propType != null) {
                //取出ResultSet中第i列的值,并转化成propType类型。
                value = this.processColumn(rs, i, propType);
                if (value == null && propType.isPrimitive()) {
                    //是原始类型并且为空,提供默认值。
                    value = primitiveDefaults.get(propType);
                }
            }
            //调用javabean的set方法为属性赋值
            this.callSetter(bean, prop, value);
        }
        return bean;
    }

这里列出两个主要的方法,其他的方法可以下载我github中的源码,我都写有中文注解。

toBeanList 的实现

toBeanList方法:

    public <T> List<T> toBeanList(final ResultSet rs, final Class<? extends T> type) throws SQLException {
        final List<T> results = new ArrayList<>();
        if (!rs.next()) {
            return results;
        }
        final PropertyDescriptor[] props = this.propertyDescriptors(type);
        final ResultSetMetaData rsmd = rs.getMetaData();
        final int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
        do {
            results.add(this.createBean(rs, type, props, columnToProperty));
        } while (rs.next());
        return results;
    }

createBean方法:

    private <T> T createBean(final ResultSet rs, final Class<T> type,
                             final PropertyDescriptor[] props, final int[] columnToProperty)
            throws SQLException {
        final T bean = this.newInstance(type);
        return populateBean(rs, bean, props, columnToProperty);
    }

这个是很好理解的,看懂了前面toBean的实现,这里就自然而然理解了。

梳理一下:从 ResultSet 到 Bean

  1. 反射创建Bean对象
  2. 获取Bean属性的描述数组PropertyDescriptor[]
  3. 获取ResultSet结果集中字段的信息ResultSetMetaData
  4. 匹配Bean属性和ResultSet结果集中字段,如果没有自定义列名与属性对应的 map,那么默认使用忽略大小写的属性名与列名对应,此时下划线与驼峰是无法匹配的,不过可以用BeanProcessor的子类GenerousBeanProcessor解决
  5. Bean的属性赋值,赋值成功的前提是属性要与对应的字段匹配上,并且java类型要与数据库字段类型对应上

附上我的github地址,dbutils源码和我自己加的注解。

猜你喜欢

转载自blog.csdn.net/m0_37659871/article/details/81562568