<collection>
集合的嵌套结果映射就是指通过一次SQL查询将所有的结果查询出来,然后映射到不同的对象中。在一对多的关系中,主表一条数据会对应关联表的多条数据。因此一般查询时会查询出多条结果,按照一对多的数据映射时,最终的结果数会小于等于查询的总记录数。
使用场景:在博客系统中,文章分类自身包含多个子类
实体类如下:
@Data
public class ArticleType {
private Integer id;
private String text;
private String href;
private String parentid;
private String publishdate;
private String updatedate;
private List<ArticleType> nodes;
private List<Integer> tags;
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.blog.mapper.ArticleTypeMapper" >
<resultMap id="BaseResultMap" type="com.blog.model.ArticleType" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="text" property="text" jdbcType="VARCHAR" />
<result column="href" property="href" jdbcType="VARCHAR" />
<result column="parentid" property="parentid" jdbcType="VARCHAR" />
<result column="publishDate" property="publishdate" jdbcType="VARCHAR" />
<result column="updateDate" property="updatedate" jdbcType="VARCHAR" />
<collection property="nodes" ofType="com.blog.model.ArticleType">
<id column="nodeid" property="id" jdbcType="INTEGER" />
<result column="nodetext" property="text" jdbcType="VARCHAR" />
<result column="nodehref" property="href" jdbcType="VARCHAR" />
<result column="nodeparentid" property="parentid" jdbcType="VARCHAR" />
<result column="nodepublishDate" property="publishdate" jdbcType="VARCHAR" />
<result column="nodeupdateDate" property="updatedate" jdbcType="VARCHAR" />
</collection>
</resultMap>
<sql id="Base_Column_List" >
id, text, href, parentid, publishDate, updateDate
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from articletype
where id = #{id,jdbcType=INTEGER}
</select>
<select id="selectArticleTypes" resultMap="BaseResultMap">
select
a.id,
a.text,
a.href,
a.parentid,
a.publishDate,
a.updateDate,
b.id nodeid,
b.text nodetext,
b.href nodehref,
b.parentid nodeparentid,
b.publishdate nodepublishdate,
b.updateDate nodeupdatedate
from articleType a
left outer join articleType b on b.parentid=a.id
where a.parentid is null
</select>
</mapper>
查询之后形成如下数据结构
[{
"href": "#parent1",
"id": 1,
"nodes": [{
"href": "#child1",
"id": 2,
"parentid": "1",
"publishdate": "2019-02-16",
"text": "框架"
}, {
"href": "#child4",
"id": 7,
"nodes": [],
"parentid": "1",
"publishdate": "2019-02-16",
"text": "多线程"
}],
"publishdate": "2019-02-16",
"text": "Java"
}, {
"href": "#parent2",
"id": 4,
"nodes": [{
"href": "#child2",
"id": 5,
"nodes": [],
"parentid": "4",
"publishdate": "2019-02-16",
"text": "Oracle"
}, {
"href": "#child3",
"id": 6,
"nodes": [],
"parentid": "4",
"publishdate": "2019-02-16",
"text": "Mysql"
}],
"publishdate": "2019-02-16",
"text": "数据库"
}]
Mybatis结果集的合并原理
Mybatis在处理结果集时,首先会根据resultMap中配置的<id>属性判断结果是否相同,<id>属性相当于表记录的主键,如果<id>相同则认为是相同的记录则合并。如果resultMap没有配置<id>属性,则会把resultMap中配置的所有字段进行比较,如果所有字段都相同则合并。只要有一个不相同都不合并。
因此建议所有resultMap都配置<id>属性以提高查询效率。
多层树结构问题
使用collection对不会迭代查询,子元素中如何还有子元素并没有办法直接查询出来,试了很多方法也没有办法,如果有知道的小伙伴看到还希望能不吝指教,我在实际应用中因为可以确定文章类型的结构层次为3层,所以在<collection>下又包装了一层<collection>,这样就可以获取到三层数据