一.association(多对一、一对一嵌套)
在MyBatis查询过程中,有时会出现多对一、一对一的复杂嵌套查询,比如查询学生及其对应的班级、查询学生及其所在学校、查询评论及其发布用户等。对于这种查询需求,最简单的就是分多次查询,那么如何在一次查询处理中查询所需要的所有结果呢?这里就需要
associatio 字段的应用。
1.实体类关联关系
2.方式一:association+resultMap嵌套
- association属性字段中,如果实体类属性字段名与查询出来的字段名在ResultMap中可以一一对应,则不需要重命名,直接查询即可。
- association属性字段中,如果实体类属性字段名与查询出来的字段名存在不同,则可以通过as关键字进行重命名,比如 select c.c_id as comment_id, ...
- 在查询中可以指定查询字段,没有查到的字段在实体类中会自动赋值为null
<resultMap id="commentEntityMap" type="CommentEntity">
<id property="commentId" column="comment_id"></id>
<result property="commentContent" column="comment_content"></result>
<result property="commentCreate" column="comment_create"></result>
<result property="commentBlogid" column="comment_blogid"></result>
<!--此处必须要指明javaType类型限定,否则会报错-->
<association property="commentUser" javaType="User">
<id property="userId" column="user_id"></id>
<result property="userName" column="user_name"></result>
<result property="userNickname" column="user_nickname"></result>
<result property="userPassword" column="user_password"></result>
<result property="userRole" column="user_role"></result>
<result property="userImgurl" column="user_imgurl"></result>
<result property="userStatus" column="user_status"></result>
</association>
</resultMap>
<select id="selectAll" resultMap="commentEntityMap">
select c.comment_id,c.comment_content,c.comment_create,c.comment_blogid,u.user_id,u.user_name,u.user_nickname,u.user_imgurl
from comment c,user u
where c.comment_userid = u.user_id
</select>
3.方式二: association+resultMap引用
<mapper namespace="com.zju.sdust.weblog.dao.ICommentDao">
<resultMap id="commentEntityMap" type="CommentEntity">
<id property="commentId" column="comment_id"></id>
<result property="commentContent" column="comment_content"></result>
<result property="commentCreate" column="comment_create"></result>
<result property="commentBlogid" column="comment_blogid"></result>
<!--使用命名空间限定的ResultMap 引用 userMap -->
<association property="commentUser" resultMap="com.zju.sdust.weblog.dao.IUserDao.userMap"></association>
</resultMap>
<select id="selectAll" resultMap="commentEntityMap">
select c.comment_id,c.comment_content,c.comment_create,c.comment_blogid,u.user_id,u.user_name,u.user_nickname,u.user_imgurl
from comment c,user u
where c.comment_userid = u.user_id
</select>
</mapper>
注意:如果关联查询表之间存在重名字段,
- 若该字段关联大表和小表都有,则可以不用管直接查询即可
- 若该字段只保留一个,则可以通过association 的
columnPrefix
属性:当连接多个表时,你可能会不得不使用列别名来避免在 ResultSet 中产生重复的列名。指定 columnPrefix 列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中。举例如下:
<mapper namespace="org.hsnotebook.mapper.BlogMapper">
<resultMap id="blogResultMap" type="org.hsnotebook.entity.Blog">
<id property="id" column="id" />
<result property="title" column="title" />
<association property="author" resultMap="org.hsnotebook.mapper.AuthorMapper.authorResultMap" columnPrefix="a_">
</association>
</resultMap>
<!--带有a_前缀的属性就会自动映射到association小表中-->
<select id="selectBlog" resultMap="blogResultMap">
select
b.id,
b.title,
b.author_id,
a.id as a_id,
a.name as a_name,
from
t_blog b left join t_author a on a.id = b.author_id
</select>
</mapper>
4.方式三: association+select查询嵌套
这种方式是使用一条单独的select语句来加载关联的实体,然后在association元素中引用此select语句。相当于查询了一次学生表,查询了N次班级表,每次学生表查询都会触发select查询,因此会产生N+1问题,尽量不要用嵌套的select语句。
<resultMap type="com.mysteel.entity.Student" id="studentMap">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="age" column="age" />
<!-- 一对一关联:单向。方式五:使用select引用 -->
<association property="stuClass" column="class_id"
select="com.mysteel.dao.ClassDao.selectById" fetchType="lazy" />
</resultMap>
<select id="selectById" parameterType="Integer" resultMap="studentMap" >
select id, name, age, class_id
from student s
where s.id = #{id}
</select>
<resultMap type="com.mysteel.entity.Class" id="classMap">
<id property="id" column="class_id" />
<result property="className" column="class_name" />
</resultMap>
<select id="selectById" resultMap="classMap" parameterType="int">
select id class_id, class_name from class where id = #{class_id}
</select>
二.collection(一对多嵌套)
collection用于处理MyBatis中一对多的嵌套查询关系,比如查询部门及其所有员工、查询老师及其所有学生等。在collection中有几个字段需要说明一下:
- property:实体类中对应的属性名
- javaType:查询结果类型,一般为列表List,可以不写
- ofType:结果集中的数据类型
- select:嵌套子查询语句
- column:表示子查询参数是父查询的哪个字段
<!-- 通用查询映射结果 -->
<resultMap id="productResultMap" type="org.springblade.product.entity.Position">
<result column="id" property="id"/>
<result column="tPosName" property="tPosName"/>
<collection property="teachers" javaType="java.util.ArrayList" ofType="org.springblade.product.entity.Teacher">
<result column="id" property="id"/>
<result column="tNo" property="tNo"/>
<result column="tName" property="tName"/>
</collection>
</resultMap>
<select id="query" resultMap="productResultMap" resultType="org.springblade.product.entity.Position">
select t_pos_name as tPosName,t.t_name as tName,t.t_no as tNo from tb_position p
left join tb_teacher t on p.id=t.position_id where p.id=#{id}
and t.t_name = #{tPosName}
</select>
三.extends 继承拓展
在类关系中有继承关系,在继承关系中就存在着两个嵌套的实体类。为了在MyBatis查询过程中配合类间继承关系的实现,减少查询语句冗余,提高可拓展性,就有了ResultMap的继承拓展,通过extends实现。
1.继承关系实体类举例
public class Comment {
private Integer commentId;
private String commentContent;
private String commentCreate;
private Integer commentBlogid;
private Integer commentUserid;
}
public class CommentVo extends Comment {
private User commentUser;
}
2.XML文件配置
<mapper namespace="com.zju.sdust.weblog.dao.ICommentDao">
<!--父类resultMap-->
<resultMap id="commentMap" type="Comment">
<id property="commentId" column="comment_id"></id>
<result property="commentContent" column="comment_content"></result>
<result property="commentCreate" column="comment_create"></result>
<result property="commentBlogid" column="comment_blogid"></result>
<result property="commentUserid" column="comment_userid"></result>
</resultMap>
<!--子类resultMap:使用 extends + association 实现,继承父类属性字段,并拓展子类字段User-->
<resultMap id="commentVoMap" type="CommentVo" extends="commentMap">
<association property="commentUser" resultMap="com.zju.sdust.weblog.dao.IUserDao.userMap"></association>
</resultMap>
<!--子类查询语句-->
<select id="selectAll" resultMap="commentVoMap">
select c.comment_id,c.comment_content,c.comment_create,c.comment_blogid,u.user_id,u.user_name,u.user_nickname,u.user_imgurl
from comment c,user u
where c.comment_userid = u.user_id
</select>
</mapper>