MyBatis - 10 - 处理“多对一”/“一对多”映射关系 + MyBatis延时加载

1.准备工作

1.1 建表

t_emp
在这里插入图片描述
在这里插入图片描述

t_dept
在这里插入图片描述
将两张表建立关系
在这里插入图片描述

添加测试数据:
在这里插入图片描述
在这里插入图片描述

1.2 创建Maven项目

1.2.1 在pom文件中,修改打包方式为jar包,导入依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.rqs.mybatis</groupId>
   <artifactId>MyBatis_demo2</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <dependencies>
       <!-- Mybatis核心 -->
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.7</version>
       </dependency>

       <!-- junit测试 -->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.12</version>
           <scope>test</scope>
       </dependency>

       <!-- MySQL驱动 -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.3</version>
       </dependency>

       <!-- log4j日志 -->
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>1.2.17</version>
       </dependency>
   </dependencies>

</project>
1.2.2 创建日志配置文件和jdbc.properties

** log4j.xml**

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
   <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
       <param name="Encoding" value="UTF-8" />
       <layout class="org.apache.log4j.PatternLayout">
           <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}
%m  (%F:%L) \n" />
       </layout>
   </appender>
   <logger name="java.sql">
       <level value="debug" />
   </logger>
   <logger name="org.apache.ibatis">
       <level value="info" />
   </logger>
   <root>
       <level value="debug" />
       <appender-ref ref="STDOUT" />
   </root>
</log4j:configuration>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
1.2.3 创建Mybatis核心配置文件

** mybatis-config.xml**

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>



    <!--    MyBatis核心配置文件,标签的顺序
        properties?,settings?,typeAliases?,typeHandlers?,
        objectFactory?,objectWrapperFactory?,reflectorFactory?,
        plugins?,environments?,databaseIdProvider?,mappers?-->

    <properties resource="jdbc.properties"></properties>

    <!-- 设置MyBatis的全局配置-->
    <settings>
        <!--将_自动映射为驼峰 , emp_name:empName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>



    <!--设置类型别名,大小写不敏感。
        如果不设置alias,则默认为类名(大小写不敏感)-->
    <typeAliases>
        <!--
            typeAlias: 设置某个类型的别名
            属性:
                type 设置需要设置别名的类型
                alias 设置某个类型的别名,如果不设置该属性,那么该类型拥有默认的类名,且不区分大小写
        -->
        <!--<typeAlias type="com.rqs.mybatis.pojo.User" alias="User"></typeAlias>-->

        <!--推荐以包为单位,将包下所有的类型设置默认的类型别名且不区分大小写-->
        <package name="com.rqs.mybatis.pojo"/>
    </typeAliases>



    <!--设置连接数据库的环境-->
    <!--每一个environment都是具体连接数据库的环境-->
    <!--
        一个项目中只会用一个环境,default用于使用默认使用的环境:
        id:表示连接数据库的环境的唯一标识 不能重复

    -->
    <environments default="development">
        <!--
        transactionmanager:设置事务管理方式
        属性:
            type="JDBC/MANAGED"
            JDBC: 在当前环境中,执行sql时,使用的时jdbc原声的事务管理方式,需要手动的提交和回滚事务
            MANAGED:被管理,例如Spring
        -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--        dataSource:配置数据源
            属性"
                type:设置数据源的类型
                type=""
                POOLED:表示使用数据库连接池缓存数据库连接
                UNPOOLED:表示不使用数据库连接池
                JNDI:表示使用上下文中的数据源
            -->
            <dataSource type="POOLED">
                <!--设置连接数据库的驱动-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--设置连接地址-->
                <property name="url" value="${jdbc.url}"/>
                <!--注意:如果在建sql表单的时候选了字符集(如utf8),
                这里的value要改成:value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8"-->
                <!--用户名和密码-->
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>


    <!--引入映射文件-->
    <mappers>
        <!--
                    推荐以包为单位引入映射文件,要求:
                        1。 mapper接口所在的包要和映射文件所在的包一致
                        2。 mapper接口要和映射文件的名字一致-->
        <!--        com.rqs.mybatis.mapper创建包时要用/分隔,这样才是目录,否则这整一个就只是文件夹名字而已-->
        <package name="com.rqs.mybatis.mapper"/>
    </mappers>


</configuration>


1.2.4 创建实体类以及实体类之间的关系

Dept类:

package com.rqs.mybatis.pojo;


public class Dept {

    private Integer did;

    private String deptName;

    public Dept() {
    }

    public Dept(Integer did, String deptName) {
        this.did = did;
        this.deptName = deptName;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "did=" + did +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

Emp类:

package com.rqs.mybatis.pojo;

public class Emp {
    private Integer eid;
    private String empName;
    private Integer age;
    private String sex;
    private String email;
    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Emp() {
    }

    public Emp(Integer eid, String empName, Integer age, String sex, String email, Dept dept) {
        this.eid = eid;
        this.empName = empName;
        this.age = age;
        this.sex = sex;
        this.email = email;
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                ", dept=" + dept +
                '}';
    }
}

1.2.5 设置实体类之间的多对一和一对多关系

表和表之间是有关系的,实体类和实体类之间也有映射关系,所以需要设置实体类之间的关系,例如如何描述员工所对应的部门,如何描述部分所对应的员工。
1.【多对一】,需要在“多”所对应的实体类创建“一”对应的【对象】,即在Emp类中创建Dept对象

在这里插入图片描述

package com.rqs.mybatis.pojo;

public class Emp {
    private Integer eid;
    private String empName;
    private Integer age;
    private String sex;
    private String email;
    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Emp() {
    }

    public Emp(Integer eid, String empName, Integer age, String sex, String email, Dept dept) {
        this.eid = eid;
        this.empName = empName;
        this.age = age;
        this.sex = sex;
        this.email = email;
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                ", dept=" + dept +
                '}';
    }
}

2.【一对多】,需要在“一”所对应的实体类创建“多”对应的【集合】,即在Dept类中创建Emp的集合
在这里插入图片描述

package com.rqs.mybatis.pojo;


import java.util.List;

public class Dept {

    private Integer did;

    private String deptName;

    private List<Emp> emps;

    public Dept() {
    }

    public Dept(Integer did, String deptName, List<Emp> emps) {
        this.did = did;
        this.deptName = deptName;
        this.emps = emps;
    }

    public Dept(Integer did, String deptName) {
        this.did = did;
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "did=" + did +
                ", deptName='" + deptName + '\'' +
                ", emps=" + emps +
                '}';
    }
}

1.2.6 创建SqlSession工具类

SqlSessionUtils:

package com.rqs.mybatis.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionUtils {
    public static SqlSession getSqlSession() {
        SqlSession sqlSession = null;
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            sqlSession = sqlSessionFactory.openSession(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSession;
    }
}

2 为什么要单独处理“多对一”和“一对多”关系

假如需要查询员工以及员工所对应的部门信息,那么部门信息可以通过两表联查,在员工表中把员工的部门did查出来,再在部门表中把did对应的dept_name查出来,而这两个字段无法映射员工实体类中的Dept对象,并且数据库中这两个字段并不是实体类类型,所以只能通过resultMap来自定义映射关系。
在这里插入图片描述在这里插入图片描述

3 多对一

查询员工以及员工所对应的部门信息

3.1 方案1 级联属性赋值 【简单,但用的不多】

创建EmpMapper接口及其映射文件
EmpMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;

import java.util.List;


public interface EmpMapper 
    /**
     * 查询员工以及员工所对应的部门信息
     */
    Emp getEmpAndDept(@Param("eid") Integer eid);


EmpMapper接口映射文件

<?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.rqs.mybatis.mapper.EmpMapper">

    <resultMap id="empAndDeptResultMapOne" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <result property="dept.did" column="did"></result>
        <result property="dept.deptName" column="dept_name"></result>
    </resultMap>
    <!--    Emp getEmpAndDept(@Param("eid") Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
        <!--两表联查(用左外连接方式,还有内连接或右外连接)-->
        select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid=#{eid}
    </select>



</mapper>

测试代码:
ResultMapTest:

package com.rqs.mybatis.test;


import com.rqs.mybatis.mapper.EmpMapper;
import com.rqs.mybatis.pojo.Emp;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ResultMapTest {
    @Test
    public void testGetEmpAndDept() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(1);
        System.out.println(emp);
    }

}

测试结果:
在这里插入图片描述

3.2 方案2 association

EmpMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;

import java.util.List;


public interface EmpMapper 
    /**
     * 查询员工以及员工所对应的部门信息
     */
    Emp getEmpAndDept(@Param("eid") Integer eid);


EmpMapper接口映射文件

<?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.rqs.mybatis.mapper.EmpMapper">

    <!--处理多对一映射关系 【方案2 association】-->
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
            association:处理多对一的映射关系
            property:需要处理多对一关系的属性名
            javaType:该属性的类型
        -->
        <association property="dept" javaType="Dept">
            <id property="did" column="did" ></id>
            <result property="deptName" column="dept_name" ></result>
        </association>

    </resultMap>


    <!--    Emp getEmpAndDept(@Param("eid") Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
        <!--两表联查(用左外连接方式,还有内连接或右外连接)-->
        select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid=#{eid}
    </select>



</mapper>

测试代码:
ResultMapTest:

package com.rqs.mybatis.test;


import com.rqs.mybatis.mapper.EmpMapper;
import com.rqs.mybatis.pojo.Emp;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ResultMapTest {
    @Test
    public void testGetEmpAndDept() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(1);
        System.out.println(emp);
    }

}

测试结果:
在这里插入图片描述

3.3 方案3 分步查询【用的比较多的处理方式】

3.3.1 查询员工信息

EmpMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;

import java.util.List;


public interface EmpMapper {

    /**
     * 通过分步查询查询员工以及员工所对应的部门信息
     * 分步查询第一步:查询员工信息
     */
    Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);

    /**
     * 通过分步查询查询部门以及部门中所有的员工信息
     * 分步查询第二步:根据did查询员工信息
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);

}



EmpMapper接口映射文件

<?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.rqs.mybatis.mapper.EmpMapper">

    <!--处理多对一映射关系 【方案2 association】-->
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
            association:处理多对一的映射关系
            property:需要处理多对一关系的属性名
            javaType:该属性的类型
        -->
        <association property="dept" javaType="Dept">
            <id property="did" column="did" ></id>
            <result property="deptName" column="dept_name" ></result>
        </association>

    </resultMap>


    <!--    Emp getEmpAndDept(@Param("eid") Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
        <!--两表联查(用左外连接方式,还有内连接或右外连接)-->
        select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid=#{eid}
    </select>



</mapper>
3.3.2 根据员工所对应的部门id查询部门信息

DeptMapper接口文件

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Dept;
import org.apache.ibatis.annotations.Param;

public interface DeptMapper {
    /**
     * 分步查询的第二步:根据员工所对应的did查询部门信息
     * @param did
     * @return
     */
    Dept getEmpAndDeptByStepTwo(@Param("did") int did);
}

EmpMapper.xml

<?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.rqs.mybatis.mapper.EmpMapper">


    <!--    com.rqs.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo是这条sql语句的全类名-->
    <resultMap id="empAndDeptByStepResultMap" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
                select中写什么?
                   由于需要将DeptMapper接口中的getEmpAndDeptByStepTwo()方法所查询出来的结果赋值给association中的property属性
                   而这个方法查询的结果是通过DeptMapper.xml中的sql语句查到的,所以需要知道这个sql语句的唯一标识
                   而sql的唯一标识是sql语句的命名空间namespace加上.SQLId,即com.rqs.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo
                   而命名空间namespace其实就是Mapper接口的全类名,SQLId其实就是Mapper接口中的方法名,所以也可以理解为 mapper接口的全类名.方法名
                   即   select属性中写写第二步的sql语句的namespace.SQLId或第二步的mapper接口的全类名.方法名


                select: 设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
                column:分步查询的条件  由前一个查询的结果提供
                fetchType: 当开启了全局的延迟记载后,可通过此属性手动控制延迟加载的效果
                fetchType:"lazy/eager" lazy表示延迟加载,eager表示立即加载
        -->
        <association property="dept"
                     select="com.rqs.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="did"">
        </association>
    </resultMap>

    <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
    <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
        select * from t_emp where eid = #{eid}
    </select>
</mapper>

DeptMapper.xml

<?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.rqs.mybatis.mapper.DeptMapper">
    <!--        Dept getEmpAndDeptByStepTwo(Integer did);-->
    <!--    分步查询可以实现懒加载-->
    <!-- 在mybatis-config.xml中打开MyBatis的全局配置,将_自动映射为驼峰,这样就不用谢resultMap了,直接用resultType-->
    <select id="getEmpAndDeptByStepTwo" resultType="Dept">
        select * from t_dept where did = #{did}
    </select>

</mapper>

测试代码:

package com.rqs.mybatis.test;


import com.rqs.mybatis.mapper.EmpMapper;
import com.rqs.mybatis.pojo.Emp;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ResultMapTest {
    @Test
    public void testGetEmpAndDeptByStep() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(1);
        System.out.println(emp);
    }

}

测试结果:
在这里插入图片描述

3.3.3 ⭕️ 延迟加载

分步查询的优点:可以实现延迟加载
延迟加载默认不开启,必须在核心配置文件mybatis-config.xml中设置全局配置信息:

  • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
  • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个 属性会按需加载

此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加 载)|eager(立即加载)”


通过下面的例子来测试:

由于分步查询既能查询员工信息,又能根据分步查询的第二步来查询员工所对应的部门信息,所以在获取员工信息之后,顺便去查询了部门信息,只是没有显示。如下图所示
在这里插入图片描述

在这里插入图片描述

如果获取员工信息后不进行部门信息的查询,就需要在核心配置文件的全局设置中开启延时加载,如下图所示
在这里插入图片描述

此时在获取员工姓名的结果如下图所示,不会查询部门信息

在这里插入图片描述


如果不开启延时加载,查询员工姓名后再查询部门信息,sql语句会先全部执行,执行完之后,再去获取数据。

在这里插入图片描述
在这里插入图片描述
如果开启了延时加载,此时,sql不会全部执行。要获取员工姓名的时候,则执行获取员工姓名的sql语句
要部门信息的时候,则执行获取部门信息的sql语句,这就是延时加载。在这里插入图片描述

3.3.3.1 注意

在核心配置文件mybatis-config.xml中设置了lazyLoadingEnabled和aggressiveLazyLoading的全局配置信息处理延时加载后,
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。另外还可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加 载)|eager(立即加载)”

此时可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)
在这里插入图片描述

4 一对多

根据部门id查新部门以及部门中的员工信息

4.1 方案1 collection

DeptMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Dept;
import org.apache.ibatis.annotations.Param;

public interface DeptMapper {

    /**
     * 获取部门以及部门中所有的员工信息
     */
    Dept getDeptAndEmp(@Param("did") Integer did);

}

DeptMapper.xml

<?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.rqs.mybatis.mapper.DeptMapper">

<!--
            collection:处理一对多的映射关系
            ofType:表示该属性对应的集合中存储数据的类型
-->

    <resultMap id="deptAndEmpResultMap" type="Dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="emps" ofType="Emp">
            <id property="eid" column="eid"></id>
            <result property="empName" column="emp_name"></result>
            <result property="age" column="age"></result>
            <result property="sex" column="sex"></result>
            <result property="email" column="email"></result>
        </collection>
    </resultMap>

    <!--Dept getDeptAndEmp(@Param("did") Integer did);-->
    <select id="getDeptAndEmp" resultMap="deptAndEmpResultMap">
        select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
    </select>

</mapper>

测试方法:

package com.rqs.mybatis.test;


import com.rqs.mybatis.mapper.DeptMapper;
import com.rqs.mybatis.mapper.EmpMapper;
import com.rqs.mybatis.pojo.Dept;
import com.rqs.mybatis.pojo.Emp;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ResultMapTest {
    @Test
    public void testGetEmpAndDeptByStep() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept deptAndEmp = mapper.getDeptAndEmp(1);
        System.out.println(deptAndEmp);
    }
}

测试结果:
在这里插入图片描述

4.1 方案2 分步查询

根据部门id查新部门以及部门中的员工信息

4.1.1 查询部门信息

DeptMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Dept;
import org.apache.ibatis.annotations.Param;

public interface DeptMapper {
    /**
     * 分步查询 查询部门及其所有的员工信息
     * 第一步  查询部门信息
     */
    Dept getDeptAndEmoByStepOne(@Param("did") Integer did);
}

DeptMapper.xml

<?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.rqs.mybatis.mapper.DeptMapper">


    <resultMap id="deptAndEmpResultMapOne" type="Dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="emps"
                    select="com.rqs.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    column="did">
        </collection>
    </resultMap>


    <!--Dept getDeptAndEmoByStepOne(@Param("did") Integer did);-->
    <select id="getDeptAndEmoByStepOne" resultMap="deptAndEmpResultMapOne">
        select * from t_dept where did = #{did}
    </select>

</mapper>
4.1.2 根据部门id查询部门中的所有员工

EmpMapper接口

package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;

import java.util.List;


public interface EmpMapper {
    /**
     * 分步查询 查询部门及其所有的员工信息
     * 第一步  查询部门信息
     * 本例是第二步  根据查询员工信息
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
}


EmpMapper.xml

<?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.rqs.mybatis.mapper.EmpMapper">
    <!--    分步查询-->
    <!--    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
        select * from t_emp where did = #{did}
    </select>

</mapper>

测试类:

package com.rqs.mybatis.test;


import com.rqs.mybatis.mapper.DeptMapper;
import com.rqs.mybatis.mapper.EmpMapper;
import com.rqs.mybatis.pojo.Dept;
import com.rqs.mybatis.pojo.Emp;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ResultMapTest {
    @Test
    public void testGetDeptAndEmpBySteps(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmoByStepOne(2);
        System.out.println(dept.getDeptName());
        System.out.println("-----****************======分割线=======-----****************");
        System.out.println(dept);
    }

}

测试结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值