说到mybatis的collection标签,我们肯定不陌生,可以通过它解决一对多的映射问题,举个例子一个用户对应多个系统权限,通过对用户表和权限表的关联查询我们可以得到好多条记录,但是用户信息这部分在多条记录中是重复的,只有权限不同,我们需要把这多条权限记录映射到这个用户之中,这个时候可以通过collection标签/association标签来解决(虽然assocation标签一般是解决一对一问题的,但它实际上也能实现我们的需求,可以通过后面的源码看出来)
1.1 相关代码和运行结果
实体类和mapper代码
public class Test {
public static void main(String[] args) throws IOException {
try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
// 构建session工厂 DefaultSqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserDO userDO = userMapper.getByUserId(1);
System.out.println(userDO);
}
}
}
运行结果如下,可以看到权限记录映射到属性permitDOList 的list列表了
1.2 collection部分源码解析
通过PreparedStatement查询完之后得到ResultSet结果集,之后需要将结果集解析为java的pojo类中,下面通过源码简单讲下是如何解析的
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 是否有嵌套的resultMaps
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
// 无嵌套
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
根据有无嵌套分成两层逻辑,有嵌套resultMaps就是指<resultMap>标签下有子标签<collection>或<association>,分析下第一层
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
ResultSet resultSet = rsw.getResultSet();
// 跳过offset行
skipRows(resultSet, rowBounds);
// 上一次获取的数据
Object rowValue = previousRowValue;
// 已获取记录数量小于limit
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
// 鉴别器解析
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
// 创建缓存key resultMapId + (columnName + columnValue)....
final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
// 部分对象(可能存在对象内容缺失未完全合并)
Object partialObject = nestedResultObjects.get(rowKey);
// issue #577 && #542
// 关于resultOrdered的理解,举例若查询得到四条记录a,a,b,a , 相同可以合并。
// 那么当resultOrdered=true时,最后可以得到三条记录,第一条和第二条合并成一条、第三条单独一条、第四条也是单独一条记录
// resultOrdered=false时,最后可以得到两条记录,第一条、第二条和第四条会合并成一条,第三条单独一条记录
// 另外存储到resultHandler的时机也不一样,resultOrdered=true是等遇到不可合并的记录的时候才把之前已经合并的记录存储,
// 而resultOrdered=false是直接存储的后续有合并的记录再处理添加到集合属性中
if (mappedStatement.isResultOrdered()) {
// partialObject为null,说明这一条记录不可与上一条记录进行合并了,那么清空nestedResultObjects防止之后出现有可合并的记录的时候继续合并
// 然后将记录存储到resultHandler里面
if (partialObject == null && rowValue != null) {
nestedResultObjects.clear();
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
} else {
// 处理resultSet的当前这一条记录
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
if (partialObject == null) {
// 将记录存储到resultHandler里面
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}
这段代码主要是创建了一个缓存key,主要是根据resultMapId和<id>标签的column和对应的columvalue来创建的(若没有<id>标签,则会使用所有的<result>标签的column和columnValue来创建),以此缓存键来区分记录是否可合并。nestedResultObjects是一个储存结果的map,以缓存键为key,实体类(本例中为UserDO)为value,若能以cacheKey取到值,则说明本条记录可合并。http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E7%99%BB%E5%BD%9513O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E7%99%BB%E5%BD%95%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E9%83%A813O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%A2%E6%9C%8D%E9%83%A8%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%A4%96%E8%81%94%E9%83%A813O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%A4%96%E8%81%94%E9%83%A8%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%85%AC%E5%8F%B8%E6%8E%A5%E9%80%8113O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%85%AC%E5%8F%B8%E6%8E%A5%E9%80%81%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%94%B5%E8%AF%9D%E6%8A%95%E6%B3%A813O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%94%B5%E8%AF%9D%E6%8A%95%E6%B3%A8%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%89%8B%E6%9C%BA%E4%B8%8B%E8%BD%BD13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%89%8B%E6%9C%BA%E4%B8%8B%E8%BD%BD%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E4%B8%8B%E8%BD%BD%E7%BD%91%E7%AB%9913O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E4%B8%8B%E8%BD%BD%E7%BD%91%E7%AB%99%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%B3%A8%E5%86%8C%E7%BD%91%E7%AB%9913O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%B3%A8%E5%86%8C%E7%BD%91%E7%AB%99%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%BD%91%E7%AB%99%E6%B3%A8%E5%86%8C13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%BD%91%E7%AB%99%E6%B3%A8%E5%86%8C%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%98%E7%BD%9113O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%AE%98%E7%BD%91%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%99%BB%E9%99%86%E7%BD%91%E5%9D%8013O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E7%99%BB%E9%99%86%E7%BD%91%E5%9D%80%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E6%B3%A8%E5%86%8C13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E6%B3%A8%E5%86%8C%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E5%85%85%E5%80%BC13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E5%85%85%E5%80%BC%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%BC%80%E6%88%B7%E7%94%B5%E8%AF%9D13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%BC%80%E6%88%B7%E7%94%B5%E8%AF%9D%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E8%81%94%E7%B3%BB13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E8%81%94%E7%B3%BB%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E8%81%94%E7%B3%BB13O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E6%80%8E%E4%B9%88%E8%81%94%E7%B3%BB%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%B9%B3%E5%8F%B013O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E5%B9%B3%E5%8F%B0%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E7%BC%85%E7%94%B8%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B913O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E7%BC%85%E7%94%B8%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E9%9B%86%E5%9B%A213O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E9%9B%86%E5%9B%A2%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E4%BB%A3%E7%90%86%E7%99%BB%E9%99%8613O952222I5_1s.htm
http://house.china.com.cn/sousuo/%E6%9E%9C%E5%8D%9A%E4%B8%9C%E6%96%B9%E4%BB%A3%E7%90%86%E7%99%BB%E9%99%86%E3%80%90%E7%BD%91%E5%9D%80Ny68%C2%B7CC%E3%80%91_1s.htm
http://house.china.com.cn/sousuo/%E6%9