mybatis中的多表查询

简介: 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>
   <select id="getAllEmpAndDeptOne" resultMap="empAndDeptResultMapOne">
        SELECT t_emp.*,t_dept.dept_name FROM t_emp LEFT JOIN t_dept ON t_dept.dept_id = t_emp.dept_id;
    </select>

使用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>
<select id="getAllEmpAndDeptTwo" resultMap="empAndDeptResultMapTwo">
        SELECT t_emp.*,t_dept.dept_name FROM t_emp LEFT JOIN t_dept ON t_dept.dept_id = t_emp.dept_id;
</select>

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

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="getAllEmpAndDeptByStep" resultMap="empAndDeptResultMapByStep">
        select *from t_emp;
</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>
  <select id="getAllDeptAndEmp" resultMap="deptAndEmpResultMap">
        SELECT *FROM t_dept LEFT JOIN  t_emp ON t_dept.dept_id = t_emp.dept_id ;
  </select>

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

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<Dept> getAllDeptAndEmpByStep();-->
 <select id="getAllDeptAndEmpByStep" resultMap="deptAndEmpByStepResultMap">
        SELECT *FROM t_dept ;
 </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(立即加载)


相关文章
|
3月前
|
Java 数据库连接 数据库
MyBatis之多表查询
MyBatis之多表查询
|
10月前
|
SQL XML Java
Mybatis:SQL注入问题 like模糊查询 多表查询 动态SQL
Mybatis:SQL注入问题 like模糊查询 多表查询 动态SQL
276 0
|
3月前
|
XML Java 数据库连接
【MyBatis】1、MyBatis 核心配置文件、多表查询、实体映射文件 ......
【MyBatis】1、MyBatis 核心配置文件、多表查询、实体映射文件 ......
110 0
|
3月前
|
SQL Java 数据库连接
Mybatis如何实现多表查询
Mybatis如何实现多表查询
|
11月前
|
SQL XML Java
Mybatis的多表查询操作 2
Mybatis的多表查询操作
91 1
|
11月前
|
XML Java 数据库连接
Mybatis的多表查询操作 1
Mybatis的多表查询操作
53 1
|
10月前
|
XML Java 数据库连接
“MyBatis中的关联关系配置与多表查询“
“MyBatis中的关联关系配置与多表查询“
43 0
|
SQL Java 数据库连接
|
SQL Java 数据库连接
Mybatis如何实现多表查询?
MyBatis是一个Java持久层框架,它提供了多种方式来实现多表查询。
818 0
|
SQL XML Java
如何在 MyBatis 中进行多表查询以及注解开发?
如何在 MyBatis 中进行多表查询以及注解开发?
284 0