mybatis-5-关联查询

外键查询

1、回忆外键约束

注意要在tbl_dept中添加外键

#添加外键约束
# 此处Employee为外键表,dept为主键表
# 删除Employee的数据不会影响dapt,而删除dept一定会影响employee,这是为了保证数据的一致性
alter table tbl_employee add constraint fk_emp_dept
foreign key (d_id) references tbl_dept(id);

2、sql的关联查询

SELECT e.`id` id,e.gender gender,e.`last_name` last_name,e.`email` email, e.`d_id` d_id ,d.`dept_name`
FROM tbl_employee e,tbl_dept d
WHERE e.d_id = d.id
AND e.id = 4;

3、resultMap关联查询

== 一定要注意的是:association使用的是javaType,collection使用的是ofType,如果他们使用的是分步查询,那么这两个属性都不需要写 ==

使用assocition映射封装(多对一)javaType

(不使用外键情况下)

<resultMap id="EmployeeMap" type="Employee">
    <id column="id" property="id"/>
    <result column="last_name" property="lastName"/>
    <result column="gender" property="gender"/>
    <result column="email" property="email"/>
    <!--property为联级类的名字,javaType为联级类的类别-->
    <association property="department" javaType="Department">
        <id column="did" property="id"/>
        <result column="dept_name" property="departmentName"/>
    </association>
</resultMap>

<select id="getEmployeeList" resultMap="EmployeeMap">
    select e.id,e.last_name,e.gender,e.email,d.id did,d.dept_name
    from tbl_employee e,tbl_dept d
    where e.d_id = d.id;
</select>

使用assocition分步查询(多对一)

查询员工时把员工的部门也查询出来

主要使用在数据查询很大的时候:

  • 分布查询可以做到使用现有接口方法来达到实现封装的目的
  • 分布查询可以实现延时加载,节省资源
<!--使用resultMap分步查询-->
<!--1、先按照员工id查询员工信息
    2、根据员工信息中的d_id值去查出部门信息
    3、部门设置到员工中
-->
<resultMap id="EmployeeMapStep" type="Employee">
    <id column="id" property="id"/>
    <result column="last_name" property="lastName"/>
    <result column="gender" property="gender"/>
    <result column="email" property="email"/>
    <!--association定义关联对象的封装规则、
    select:指明当前属性是调用哪个方法查出的结果
    column:指定将哪一列的值传给方法

    流程:使用select指定的方法(传入column指定的值)查除对象,把地址赋值给原来封装对象的相关属性
    -->
    <association property="department"
                 select="com.wang.Dao.DepartmentMapper.getDepartmentById"
                 column="d_id"/>
 </resultMap>
<!--    Employee getEmployeeById(Integer id);-->
<select id="getEmployeeById" resultMap="EmployeeMapStep">
    select * from tbl_employee where id =#{id};
</select>

使用collection实现映射封装(一对多)ofType

查询部门的时候把部门内包含的员工也查询出来

接口:

public interface DepartmentMapper {

    Department getDepartmentById(Integer id);

}

bean类

private int id;
private String departmentName;
private List<Employee> employeeList;

Mapper配置文件中

<resultMap id="DepartmentMap" type="Department">
    <id column="did" property="id"/>
    <result column="dept_name" property="departmentName"/>
    <!--collection定义关联集合类型的封装规则-->
    <!--我们需要把用did查询到的数据封装成Lst对像-->
    <!--
        property:属性名称
        ofType:指定集合里面的元素
    -->
    <collection property="employeeList" ofType="Employee">
        <!--定义这个集合元素中的封装规则-->
        <id column="eid" property="id"/>
        <result column="gender" property="gender"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
    </collection>
</resultMap>
<select id="getDepartmentById" resultMap="DepartmentMap">
    select d.id did,d.dept_name,e.id eid,e.last_name,e.gender,e.email
    from tbl_dept d
    left join tbl_employee e
    on d.id = e.d_id
    where d.id = #{id};
</select>

在分布查询基础上实现延时加载

之前我们在查询Employee对象时,内部的属性都将被查询出来

单这样将占用大量内存

我们需要做到:部门信息在我们需要的时候再起查询

这个时候我们只需要在分步查询的基础在全局配置上加上两个配置

<!--开启懒加载,在需要的时候才会读取数据 -->
<setting name="lazyLoadingEncoding" value="true"/>
<!--关闭强制加载,即关闭在加载实例的时候就读取全部数据-->
<setting name="aggressiveLazyLoading" value="false"/>

或者:在collection和association标签上加上fetch属性即可

<association property="department"  //不需要oftype属性
             select="com.wang.Dao.DepartmentMapper.getDepartmentById"
             column="{id = d_id}"
             fetchType="lazy"/>
            <!--fetchType表示获取数据的方式
                lazy:懒加载
                eager:立即加载
            -->

分步查询拓展-传入多个参数

有时候需要把多个字段值传入调用的方法

做法:将多个字段的值封装成Map传递

注意点:键一定要是传入方法的参数名

column="{id = d_id,name = dept_name}"

4、discriminator鉴别器使用(进行简单的判断操作)

鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装的行为

现在有这样的需求:

如果查出来是女生,就把部门信息查询出来,否则不查询

如果查出来是男生,就把last_name这一字段的值赋值给email

注意点:case里的javatype或者说javaMap不可或缺,如果加入javaMap则表示在这个case情况下我们调用另外一种sql映射规则

<mapper namespace="com.wang.Dao.EmployeeMapper">
    <!--    //获取全部员工的信息-->
    <!--    Employee getEmployeeById(int id);-->
    <resultMap id="EmployeeMap" type="Employee">

        <!--column:指定判定的列名
            javaType:列名对应的java类型,注意开头因为经过转换所以为小写-->
        <discriminator javaType="string" column="gender">
            <!--1是男生-->
            <case value="男" resultType="com.wang.Pojo.Employee">
                <id column="id" property="id"/>
                <result column="email" property="lastName"/>
                <result column="gender" property="gender"/>
                <result column="last_name" property="email"/>
<!--                <association property="department"
                             select="com.wang.Dao.DepartmentMapper.getDepartmentByDid"
                             column="d_id"/>-->
            </case>
            <!--0是女生-->
            <case value="女" resultType="com.wang.Pojo.Employee">
                <id column="id" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="gender" property="gender"/>
                <result column="email" property="email"/>
                <association property="department"
                             select="com.wang.Dao.DepartmentMapper.getDepartmentByDid"
                             column="d_id"/>
            </case>
        </discriminator>
    </resultMap>
posted @ 2021-06-07 16:05  Coder-Wang  阅读(119)  评论(0编辑  收藏  举报