首先,我们看看DBUtils的组织架构图



DBUtils架构分析-LMLPHP

一点一点来看,AbstructQueryRunner封装了PreparStatement的产生与装填,同时还包括了对数据库资源的关闭等操作。它有两个子类,QueryRunner与AsyncQueryRunner。

先说AsyncQueryRunner,看看名字我们就知道,它的异步的获取数据库信息。

我们看一小段代码:

    //AsyncQueryRunner.java
    public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
        return executorService.submit(new Callable<T>() {

            @Override
            public T call() throws Exception {
                return queryRunner.query(sql, rsh);
            }

        });
    }

看到executorService.submit与Future<T>了吧#关于异步调用的知识大家可以参见拙作

       Callable与Future



这里我们主要看QueryRunner,它里面的结构很清晰

DBUtils架构分析-LMLPHP

主要就是增,改(删),查的sql包装,构造函数等等。

通过类图,我们可以看到,QueryRunner依赖于ResultSetHandler。

看看类图我们就知道,这是一个策略模式。

ResultSetHandler就是抽象的接口。

那么ResultSetHandler是干什么的呢?

看名字,ResultSetHander,它就是处理ResultSet的。

根据需求,ResultSet得能转化成各种类型,至少得包括Bean,List<Bean>,Map,List<Map>,当然还有数组。

那具体如何转化呢?

    //BeanHandler.java
    @Override
    public T handle(ResultSet rs) throws SQLException {
        return rs.next() ? this.convert.toBean(rs, this.type) : null;
    }

这个convert就是转换的核心,在BeanHandler初始化的时候就已经有了。



代码读到这个位置,我已经产生了一些疑问。

1 在RowProcessor中既然已经有了toMap,为什么不能有toMapList与toArrayList?

2 在basicRowProcessor中toArray与toMap是自己直接完成的,而toBean与toBeanList却代理了   BeanProcessor。这又是为什么?

其实第二个问题,我想想答案估计还是:细分二字。

不过第一个问题,我确实没想明白。



关于toMapList,通过了模板模式,在AbstractListHandler<T>里调用了handleRow

    @Override
    public List<T> handle(ResultSet rs) throws SQLException {
        List<T> rows = new ArrayList<T>();
        while (rs.next()) {
            rows.add(this.handleRow(rs));
        }
        return rows;
    }

   protected abstract T handleRow(ResultSet rs) throws SQLException;

而handleRow在MapListHandler里实现,依赖于basicRowProcessor中的toMap。

AbstractListHandler存在的价值就在于把MapListHandler与ArrayListHandler关于list的循环提了上去。



我猜想,没有toMapList与toArrayList是嫌麻烦,有toBean与toBeanList是因为有BeanProcessor。

04-15 13:08