commons-dbutils-1.9.3.jar 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低, 并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
0、Dbutils的query()的实现原理:
1、万变不离其宗,查询方法只不过是封装了结果集ResultSet转换为map或list的过程。
2、具体实现方法:
(1)以BeanListHandler为例,我们期望“将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里”。代码如下:
Connection connection = JdbcUtils.getConnection();
List<User> userList = new ArrayList<>();
QueryRunner runner = new QueryRunner();
ResultSetHandler<List<User>> rsh = new BeanListHandler<User>(User.class);
userList = runner.query(connection,sql,rsh);
在上一篇博文说道,使用Statement或PreparedStatement执行查询,得到结果集ResultSet,然后对结果集遍历,再进行封装处理:
public static <T> List<T> statementExecuteQuery(Class<T> clazz, final String sql){
T entity = null;
Statement statement = null;
ResultSet resultSet = null;
List<T> queryResult = new ArrayList<>();
Connection connection= getConnection();
if (null == connection){
//log.error("Connection is null.");
return null;
}
try {
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);//过程一:得到结果集
final List<Map<String, Object>> data = converResultSetToList(resultSet);//过程二:将结果集toList
for (Map<String, Object> map : data){//过程三:将结果集中的每一行数据都封装到一个对应的JavaBean实例中
entity = clazz.newInstance();
for (Map.Entry<String, Object> entry : map.entrySet()){
String columnName = entry.getKey();
Object columnValue = entry.getValue();
BeanUtils.setProperty(entity,columnName,columnValue);
}
queryResult.add(entity);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeResource(connection,null,null,resultSet);
}
return queryResult;
}
private static List<Map<String, Object>> converResultSetToList(ResultSet resultSet) throws SQLException {
if (null == resultSet){
return null;
}
List<Map<String, Object>> data = new ArrayList<>();
ResultSetMetaData rsmd = resultSet.getMetaData();
while (resultSet.next()){
Map<String, Object> rowData = new HashMap<String, Object>();
for(int i = 0,columnCount = rsmd.getColumnCount();i < columnCount; i++){
rowData.put(rsmd.getColumnName(i + 1),resultSet.getObject(i + 1));
}
data.add(rowData);
}
return data;
}
问:Dbutils是怎么做到封装的呢? 先看看查询实现代码:
List<T> entityList = new ArrayList<>();
Connection connection = JdbcUtils.getConnection();
QueryRunner runner = new QueryRunner();
ResultSetHandler<List<User>> rsh = new BeanListHandler<User>(User.class);
entityList = (List<T>)runner.query(connection,sql,rsh);
其实很简单,就是把上面三个过程做了封装而已,封装到 runner.query(connection,sql,rsh) 方法中。
仔细一点就是,queryRunner.query(con,sql,rsh)方法有三个参数,第一个是数据库连接对象,第二个是执行数据库查询的sql语句,第三个很重主要了,就是结果集处理ResultSetHandler的实现类。也就是你要将查询出来的一什么形式返回,是返回一个数组,还是JavaBean实例,还是Map结果,还是一个具体的结果ScalarHandler。
ResultSetHandler接口,有一个 handler 方法,queryRunner.query(con,sql,rsh) 方法将查询出来的结果集交给handler 方法来进行处理,按照 rsh 具体实现类的类型来封装处理结果集。
看看源代码:
ResultSetHandler接口:
public interface ResultSetHandler<T> {
T handle(ResultSet var1) throws SQLException;
}
queryRunner.query(con,sql,rsh)方法:
public <T> T query(Connection conn, String sql, ResultSetHandler