MyBatis的高级结果映射

在日常开发对数据库的操作中,绝大部分不会仅仅限于单个表的CRUD

通常会多个表进行联合

此时就需要使用MyBatis的高级映射功能

一对一的两表联查

随便准备了两张表,进行简单演示

t_user表

image-20231121193731566-1700574056382

t_phone表

image-20231121193840556

pojo类

根据表中的字段,所以我们需要在User类中加入Phone类型的属性

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Phone phone;
}

MyBatis的映射文件配置

1、使用标签进行一对一映射

    <resultMap id="userMap" type="user">
        <id property="id" column="u_id"/>
        <result property="name" column="u_name"/>
        <result property="age" column="age"/>
        <result property="phone.id" column="p_id"/>
        <result property="phone.phone_id" column="phone_id"/>
        <result property="phone.name" column="p_name"/>
    </resultMap>

    <select id="selectUserById" resultType="user" resultMap="userMap">
        select
            u.id u_id,
            u.name u_name,
            u.age,
            p.id p_id,
            p.phone_id phone_id,
            p.name p_name
        from t_user u
            join t_phone p on u.phone_id = p.phone_id
        where
            u.id = #{id}
    </select>

image-20231121195708475

2、使用标签中的子标签

<resultMap id="userMap" type="user">
    <id property="id" column="u_id"/>
    <result property="name" column="u_name"/>
    <result property="age" column="u_age"/>
    <result property="phoneId" column="p_phone_id"/>
</resultMap>

<resultMap id="userPhoneMap" extends="userMap" type="user">
    <association property="phone" columnPrefix="p_">
        <id property="id" column="id"/>
        <result property="phone_id" column="phone_id"/>
        <result property="name" column="name"/>
    </association>
</resultMap>

<select id="selectUserById" resultType="user" resultMap="userPhoneMap">
    select
        u.id u_id,
        u.name u_name,
        u.age u_age,
        p.id p_id,
        p.phone_id p_phone_id,
        p.name p_name
    from t_user u
        join t_phone p on u.phone_id = p.phone_id
    where
        u.id = #{id}
</select>

3、分步查询

分步查询,就是将前一步的查询结果当作下一步查询的条件,

最后返回所有的结果集

那么执行分步查询的先决条件就是开启懒加载

  • 懒加载:使用时才会加载,不使用不加载

UserMapper.xml ==> 第一步

<resultMap id="userMap" type="user">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="age" column="age"/>
    <result property="phoneId" column="phone_id"/>

    <association property="phone"
                 select="com.solider.mybatis_demo.mapper.PhoneMapper.selectByPhoneId"
                 column="phone_id"
                 fetchType="lazy"/>
</resultMap>

<select id="selectUserById" resultMap="userMap">
    select * from t_user where id = #{id}
</select>
  • column:根据查询的名称数据,传入下一步需要#{}传入的参数
  • fetchType:加载类型
    • lazy:开启局部懒加载,当需要用到select指定的SQL语句时才进行加载
    • eager:关闭局部延迟加载

PhoneMapper.xml ==> 第二步

<select id="selectByPhoneId" resultType="phone">
        select * from t_phone where phone_id = #{phone_id}
</select>

一对多、多对一联查

一个班级,对应多个学生

在主表中添加集合或数组,对应多个子表对象

public class Clazz {
    private Integer cid;
    private String cname;
    private List<Student> students;
    // ...
}
  • 两种实现方式:
    • collection
    • 分步查询

collection

<resultMap id="clazzResultMap" type="Clazz">
    <id property="cid" column="cid"/>
    <result property="cname" column="cname"/>

    <!--
        property: 集合的属性名
        ofType: 集合中存放的类型
    -->
    <collection property="students" ofType="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
    </collection>
</resultMap>

分步查询

<!-- ClazzMapper.xml -->
<resultMap id="clazzResultMapStep" type="Clazz">
  <result property="cid" column="cid"/>
  <result property="cname" column="cname"/>

  <collection property="students"
              select="com.powernode.mapper.StudentMapper.selectByIdStep2"
              column="cid"/>
</resultMap>

<select id="selectByIdStep1" resultMap="clazzResultMapStep">
select * from t_clazz where cid = #{cid}
</select>
<!-- StudentMapper.xml -->
<select id="selectByIdStep2" resultType="Student">
  select * from t_student where cid = #{cid}
</select>