MyBatis对JDBC做了很好的封装,其中一个吸引人的地方就是能够对从数据库内查询出来的表的记录集映射生成一系列JavaBean,供应用程序使用。今天跟着源码一层一层探讨一下MyBatis把数据库记录集映射到POJO对象的一个简要的过程。
1. DefaultResultSetHandler类
处理结果集的主要实现类,先从这个方法看
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if(parentMapping != null) {
this.handleRowValues(rsw, resultMap, (ResultHandler)null, RowBounds.DEFAULT, parentMapping);
} else if(this.resultHandler == null) {
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(this.objectFactory);
this.handleRowValues(rsw, resultMap, defaultResultHandler, this.rowBounds, (ResultMapping)null);
multipleResults.add(defaultResultHandler.getResultList());
} else {
this.handleRowValues(rsw, resultMap, this.resultHandler, this.rowBounds, (ResultMapping)null);
}
} finally {
this.closeResultSet(rsw.getResultSet());
}
}
它有这样一些类型的参数:ResultSetMapper、ResultMap、一个List、ResultMapping,上面的的代码主要是用到了这个类自己的方法handleRowValues,并需要一个DefaulResultHandler的对象,
handleRowValues方法把处理后的结果列表添加到List<object>内,可以得出一个初步结论:
不管方法handleRowValues里面调用的层次多深,最终把结果集ResultSet经过处理,得到了需要的那些POJO对象并存储到一个List里面。
2. 来看一下方法handleRowValues方法:
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if(resultMap.hasNestedResultMaps()) {
this.ensureNoRowBounds();
this.checkResultHandler();
this.handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
this.handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
又多了一个RowBounds类型的参数,点进去看一下,封装了limit和offset的一个类,应该是拿来传入limit和offset参数用的,方法中分两种情况分别调用了两个方法,前一种是resultMap中有嵌套,后一种没有嵌套,这里重点看看后一种方法,ResultMap是包装了数据表列和对象属性等信息的一个类。
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>(