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;
}