Commons-dbutils中的queryrunner来对sql语句进行操作源码追踪

 

QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());

runner.query(sql语句,new BeanListHandler<User>(User.class),参数 );

QueryRunner的执行需要绑定数据源,或者向其中传入一个connection 

1.先来看resultsethandler的实现类 

通常在查询情况下 使用beanlisthandler ,就仅仅追踪下beanlisthandler。

调用BeanListHandler构造函数  需要传递要封装的bean类型(type),并且默认传递了convert转换器 (自动传入

public class BeanListHandler<T> implements ResultSetHandler<List<T>> {

    public BeanListHandler(Class<T> type) {

        this(type, ArrayHandler.ROW_PROCESSOR);

    }

    public BeanListHandler(Class<T> type, RowProcessor convert) {  //RowProcessor是一个接口 接口实现类是

        this.type = type;

        this.convert = convert;

}

}

//RowProcessor是一个接口 接口实现类是

ArrayHandler.ROW_PROCESSOR  属于RowProcessor,封装在ArrayHandler

查看默认封装的ArrayHandler.ROW_PROCESSOR = new BasicRowProcessor();

public class ArrayHandler implements ResultSetHandler<Object[]> {

static final RowProcessor ROW_PROCESSOR = new BasicRowProcessor();

}

继续往下查看层层甩锅 ,BasicRowProcessor的无参构造调用有参构造 ,传入BeanProcessor,终于要接近本质了 

public class BasicRowProcessor implements RowProcessor {

private static final BeanProcessor defaultConvert = new BeanProcessor();

    public BasicRowProcessor() {

        this(defaultConvert);

}

//最终执行这个方法  默认传递一个BeanProcessor 对象 就是一个转换器

    public BasicRowProcessor(BeanProcessor convert) {

        super();

        this.convert = convert;

    }

}

终于到本质了 

追踪BeanProcessor的构造方法 ,里面包含了静态方法 ,封装了一个初始化的hanshmap  键值对是类型和初始化值。

public class BeanProcessor {

     private static final Map<Class<?>, Object> primitiveDefaults = new HashMap<Class<?>, Object>();

     static {

        primitiveDefaults.put(Integer.TYPE, Integer.valueOf(0));

        primitiveDefaults.put(Short.TYPE, Short.valueOf((short) 0));

        primitiveDefaults.put(Byte.TYPE, Byte.valueOf((byte) 0));

        primitiveDefaults.put(Float.TYPE, Float.valueOf(0f));

        primitiveDefaults.put(Double.TYPE, Double.valueOf(0d));

        primitiveDefaults.put(Long.TYPE, Long.valueOf(0L));

        primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);

        primitiveDefaults.put(Character.TYPE, Character.valueOf((char) 0));

    }

    public BeanProcessor() {

        super();

    }

}

查看querryrunner的执行过程

private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params)

            throws SQLException {
      //判断连接是否可用
        if (conn == null) {
            throw new SQLException("Null connection");
        }
      //sql语句是否为空
        if (sql == null) {
            if (closeConn) {
               close(conn);
            }
            throw new SQLException("Null SQL statement");
        }
        if (rsh == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null ResultSetHandler");
        }
    
   //调用底层sql操作
        PreparedStatement stmt = null;
        ResultSet rs = null;
   //t   要返回的封装对象
        T result = null;
        try {
         //预处理 sql和连接
            stmt = this.prepareStatement(conn, sql);      
         //参数填充
            this.fillStatement(stmt, params);
         //返回结果集
            rs = this.wrap(stmt.executeQuery());
         //对结果集进行处理 封装到对象中
           result = rsh.handle(rs);
        } catch (SQLException e) {
            this.rethrow(e, sql, params);
        } finally {
            try {
                close(rs);
            } finally {
                close(stmt);
                if (closeConn) {
                   close(conn);
                }
            }
        }
        return result;
    }

 

//分析参数是如何填充的

public void fillStatement(PreparedStatement stmt, Object... params) throws SQLException {


        // check the parameter count, if we can
        ParameterMetaData pmd = null;
        if (!pmdKnownBroken) {
            pmd = stmt.getParameterMetaData();
            int stmtCount = pmd.getParameterCount();
            int paramsCount = params == null ? 0 : params.length;
            if (stmtCount != paramsCount) {
                throw new SQLException("Wrong number of parameters: expected "

                        + stmtCount + ", was given " + paramsCount);
            }
        }

        // nothing to do here
        if (params == null) {
            return;
        }

        for (int i = 0; i < params.length; i++) {
            if (params[i] != null) {
                stmt.setObject(i + 1, params[i]);
            } else {

                // VARCHAR works with many drivers regardless
               // of the actual column type.  Oddly, NULL and
                // OTHER don't work with Oracle's drivers.
                int sqlType = Types.VARCHAR;
                if (!pmdKnownBroken) {
                    try {
                        sqlType = pmd.getParameterType(i + 1);
                    } catch (SQLException e) {
                        pmdKnownBroken = true;
                    }
                }

                stmt.setNull(i + 1, sqlType);

            }

        }

    }


 

// Beanhandlerlist类调用handler方法对结果进行封装处理

 

public class BeanListHandler<T> implements ResultSetHandler<List<T>> {

    public List<T> handle(ResultSet rs) throws SQLException {

        return this.convert.toBeanList(rs, type);

    }

}

 

最终的封装处理方法是

public class BeanProcessor {

   */

    public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException {

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

private <T> T createBean(ResultSet rs, Class<T> type,
            PropertyDescriptor[] props, int[] columnToProperty)
            throws SQLException {
        T bean = this.newInstance(type);
        for (int i = 1; i < columnToProperty.length; i++) {
            if (columnToProperty[i] == PROPERTY_NOT_FOUND) {
                continue;
            }

            PropertyDescriptor prop = props[columnToProperty[i]];
            Class<?> propType = prop.getPropertyType();
           Object value = this.processColumn(rs, i, propType);
            if (propType != null && value == null && propType.isPrimitive()) {
                value = primitiveDefaults.get(propType);
            }
            this.callSetter(bean, prop, value);
        }
        return bean;
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值