一.association(多对一、一对一嵌套)

        在MyBatis查询过程中,有时会出现多对一、一对一的复杂嵌套查询,比如查询学生及其对应的班级、查询学生及其所在学校、查询评论及其发布用户等。对于这种查询需求,最简单的就是分多次查询,那么如何在一次查询处理中查询所需要的所有结果呢?这里就需要

associatio 字段的应用。

1.实体类关联关系

mybatis foreach 嵌套if test mybatis嵌套子查询_linq

mybatis foreach 嵌套if test mybatis嵌套子查询_字段_02

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>