mybatis中的多表查询

首先我们先创建两个表和pojo用来演示多表查询,如下:
用户表:t_emp表,其中emp_id为自增主键。
在这里插入图片描述
t_emp对应的pojo:Employee

public class Employee {
    private Integer empId;

    private String empName;

    private  Integer age;

    private String gender;

    private Dept dept;

    public Employee(Integer empId, String empName, Integer age, String gender, Dept dept) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
        this.dept = dept;
    }
    public Employee() {
    }

   //Setter and Getter方法必须要有,这里不在展示
    
    @Override
    public String toString() {
        return "Employee{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

部门表:t_dept,dept_id为主键

在这里插入图片描述
对应的pojo:Dept

public class Dept {
    private Integer deptId;

    private String deptName;

    private Collection<Employee> employees;

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

    public Dept() {
    }

     //Setter and Getter方法必须要有,这里不在展示
     
    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", employees=" + employees +
                '}';
    }
}

在核心配置文件中的Setting的配置

<settings>
        <!--将下滑线映射为驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

IDEA中的目录
在这里插入图片描述

多对一查询

多对一查询:第一张表中的多条记录可能对应第二张表中的一条记录,并且在第一张表对应的类中存在第二张表对应类的实例变量。对应到例子中,员工表中,不同的员工肯属于同一个部门,员工表中有部门类型的实例。这里提供三种查询方式。

使用级联处理映射关系

EmployeeMapper.xml中:

<!--
        resultMap的属性:
        id:该映射的唯一标识
        type:处理映射关系的实体类的类型。

        内部标签:
        id:处理主键和实体类属性的映射关系
        result:处理普通字段和实体类属性的映射关系
                column:字段名   property:映射的属性名
    -->
   <resultMap id="empAndDeptResultMapOne" type="pojo.Employee">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>
        <result column="dept_id" property="dept.deptId"/>
        <result column="dept_name" property="dept.deptName"/>
   </resultMap>

使用asscoiation处理映射关系

EmployeeMapper.xml中:

 <resultMap id="empAndDeptResultMapTwo" type="pojo.Employee">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName">/</result>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>
        <!--
            association:处理多对一的映射关系(处理实体类型的属性)
                property:要处理的实体类型的属性
                javaType:该属性的实体类型
        -->
        <association property="dept" javaType="pojo.Dept">
            <id column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
        </association>
</resultMap>

使用分步查询处理映射关系

DeptMapper中:

<!--在本次分步查询中属于第二步查询-->
<select id="getDeptById" resultType="pojo.Dept">
        select *from t_dept where dept_id = #{dept_id};
</select>

EmployeeMapper.xml中:

<resultMap id="empAndDeptResultMapByStep" type="pojo.Employee">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>

        <!--
            使用分步查询对某一属性进行映射
            property:需要进行映射处理的实体类属性
            select:分步查询的唯一标识
            column:分步查询所需要的参数(由第一次查询提供)
            dept属性由第二步查询来获取
        -->
        <association property="dept"
                     select="mapper.DeptMapper.getDeptById"
                     column="dept_id"/>
</resultMap>

 <select id="getDeptById" resultType="pojo.Dept">
        select *from t_dept where dept_id = #{deptId};
</select>

一对多查询

一对多查询:第一张表中的一条记录对应第二张表中的多条记录,并且在第一张表对应类中有第二张表对应类中的实例集合属性。对应到例子当,一个部门可能会有多个员工,相应的部门表对应类中有List集合类型的属性。这里提供两种查询方式。

使用collection处理映射关系

DeptMapper中:

<resultMap id="deptAndEmpResultMap" type="pojo.Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
        <!--collection:用于处理一对多的查询-->
        <collection property="employees" ofType="pojo.Employee">
            <id column="emp_id" property="empId"/>
            <result column="emp_name" property="empName"/>
            <result column="age" property="age"/>
            <result column="gender" property="gender"/>
        </collection>
  </resultMap>

使用分步查询处理映射关系

EmployeeMapper.xml中:

<select id="getEmpByDept" resultType="pojo.Employee">
        select *from t_emp where dept_id = #{dept_id};
</select>

DeptMapper中:

<resultMap id="deptAndEmpByStepResultMap" type="pojo.Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
        <collection property="employees" ofType="Employee" select="mapper.EmpMapper.getEmpByDept" column="dept_id"/>
 </resultMap>
 <!--List<Employee> getEmpByDept();-->
 <select id="getEmpByDept" resultType="pojo.Employee">
     select *from t_emp where dept_id = #{dept_id};
 </select>

分步查询的延迟加载和按需加载

在mybatis的核心配置文件当中可以配置这两种属性。

<settings>
        <!--延迟加载的全局开关,默认为false关闭。当开启时,所有关联对象都会延迟加载-->
        <setting name="lazyLoadingEnabled" value="false"/>
        <!--完整加载的全局开关,在mybatis版本大于3.4.1时,默认为false关闭,为按需加载。在启用时,延迟加载的任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
</settings>

按需加载:按需加载又称懒加载,在需要时才会去加载。我们以多对一的分步查询为例。

@Test
    public void testGetAllEmpAndDeptByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        List<Employee> employeeList = empMapper.getAllEmpAndDeptByStep();
        employeeList.forEach((Employee employee) ->{
            System.out.println(employee.getEmpName());
        });
    }

我们在设置属性lazyLoadingEnabled之前:
编译后的日志记录如下:
在这里插入图片描述
尽管我们只需要emp_name,仅通过select * from t_emp就可以将所需数据查出来,但是我们还是进行了两步查询。

我们将属性lazyLoadingEnabled设置为true,aggressiveLazyLoading默认为false,所以此时是按需加载。

编译后的日志记录如下:
在这里插入图片描述
因为需要的对象仅通过select * from t_emp就能得出,所以只会进行这一次查询。

此时我们再将属性aggressiveLazyLoading设置为true,编译后的日志记录如下:
在这里插入图片描述
此时不在是按需加载,而是完整加载。

在按需加载时,我们可以在collection标签或者是association标签中设置的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加载)|eager(立即加载)

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值