> 文档中心 > 【Mybatis从入门到实战教程】第六章 Mybatis 延迟加载详解

【Mybatis从入门到实战教程】第六章 Mybatis 延迟加载详解


六、Mybatis 延迟加载

6.1 什么是延迟加载

    需要查询关联信息时,使用MyBatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载。
    
    懒加载针对级联使用的,懒加载的目的是减少内存的浪费和减轻系统负担。你可以理解为按需加载,当我调用到关联的数据时才与数据库交互否则不交互。
    
    resultMap可以实现高级映射(使用association、collection实现一对一和一对多映射),association、collection具备延迟加载功能。

6.2 打开延迟加载开关

    在MyBatis核心配置文件中配置:lazyLoadingEnabled、aggressiveLazyLoading。

设置项 描述 允许值 默认值
lazyLoadingEnabled 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载 true, false false
aggressiveLazyLoading 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载 true, false true
            

6.3 实体类

6.3.1 部门

public class Dept {    private Integer deptno;    private String dname;    private String loc;    /**     * 关系属性     */    private List empList;    public Integer getDeptno() { return deptno;    }    public void setDeptno(Integer deptno) { this.deptno = deptno;    }    public String getDname() { return dname;    }    public void setDname(String dname) { this.dname = dname;    }    public String getLoc() { return loc;    }    public void setLoc(String loc) { this.loc = loc;    }    public List getEmpList() { return empList;    }    public void setEmpList(List empList) { this.empList = empList;    }    @Override    public String toString() { return "Dept{" +  "deptno=" + deptno +  ", dname='" + dname + '\'' +  ", loc='" + loc + '\'' +  '}';    }}

6.3.2 员工类

public class Emp {    private Integer empno;    private String ename;    private String job;    private Integer mgr;    private Date hiredate;    private Double sal;    private Double comm;    private Integer deptno;    /**     * 关系属性     */    private Dept dept;    public Integer getEmpno() { return empno;    }    public void setEmpno(Integer empno) { this.empno = empno;    }    public String getEname() { return ename;    }    public void setEname(String ename) { this.ename = ename;    }    public String getJob() { return job;    }    public void setJob(String job) { this.job = job;    }    public Integer getMgr() { return mgr;    }    public void setMgr(Integer mgr) { this.mgr = mgr;    }    public Date getHiredate() { return hiredate;    }    public void setHiredate(Date hiredate) { this.hiredate = hiredate;    }    public Double getSal() { return sal;    }    public void setSal(Double sal) { this.sal = sal;    }    public Double getComm() { return comm;    }    public void setComm(Double comm) { this.comm = comm;    }    public Integer getDeptno() { return deptno;    }    public void setDeptno(Integer deptno) { this.deptno = deptno;    }    public Dept getDept() { return dept;    }    public void setDept(Dept dept) { this.dept = dept;    }    @Override    public String toString() { return "Emp{" +  "empno=" + empno +  ", ename='" + ename + '\'' +  ", job='" + job + '\'' +  ", mgr=" + mgr +  ", hiredate=" + hiredate +  ", sal=" + sal +  ", comm=" + comm +  ", deptno=" + deptno +  '}';    }}

6.4 使用association实现延迟加载

    查询员工以及相关联的部门信息。

6.4.1 mapper接口

public interface EmpMapper {    /*     * 查询所有员工的信息,并关联查询部门信息     */    List select();}public interface DeptMapper {    /*     * 根据部门编号查询部门信息     */    Dept selectById(Integer deptno);}

6.4.2 mapper文件

    懒加载的前提是需要分离Sql,不再使用关联查询Sql。
    
    比如我们要查询所有员工的信息,并关联查询部门信息;想要实现部门信息懒加载,那么查询员工信息是一条独立的Sql,根据部门编号查询部门信息也是一条独立的Sql,当查询员工信息的时候,如果需要用到部门信息,那么就调用根据部门编号查询部门信息的Sql。

根据部门编号查询部门信息:

     select deptno,dname,loc from dept where deptno=#{deptno}    

查询员工信息(单表查询),并通过上边的查询去关联部门信息:

    association标签的属性:
        select:执行延迟加载时关联数据查询的sql对应的statementId。
            执行的关联查询语句在同一mapper文件中:直接填入statementId即可;
            执行的关联查询语句在不同的mapper文件中:namespace.statementId;
        column:在执行关系表信息查询时,与其关联的字段名称。

                       select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp    

6.4.3 测试

public class LazyLoadingTest {    @Test    public void testOneToOne() { SqlSession sqlSession = MybatisUtil.getSession(); EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class); List list = empMapper.select(); for (Emp emp : list) {     System.out.println(emp.getEmpno() + "--" + emp.getEname() + "--" + emp.getJob());     System.out.println("----------");     // 需要使用关联信息     Dept dept = emp.getDept();     if (dept != null) {  System.out.println(dept.getDeptno() + "--" + dept.getDname() + "--" + dept.getLoc());     }     System.out.println("-----------------分割线----------------"); } sqlSession.close();    }}

6.5 使用collection实现延迟加载

6.5.1 mapper接口

public interface DeptMapper { /*     * 查询所有部门信息,并关联部门对应的员工信息     */    List select();}public interface EmpMapper {    /*     * 根据部门编号查询对应的员工信息     */    List selectByDeptno(Integer deptno);}

6.5.2 mapper文件

根据部门编号查询员工信息:

    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where deptno=#{deptno}

查询部门信息(单表查询),并通过上边的查询去关联部门中的员工信息:

                            select deptno,dname,loc from dept

6.5.3 测试

@Testpublic void testOneToMany() {    SqlSession sqlSession = MybatisUtil.getSession();    DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);    List list = deptMapper.select();    for (Dept dept : list) { System.out.println(dept.getDeptno() + "--" + dept.getDname() + "--" + dept.getLoc()); //查询关联信息 List empList = dept.getEmpList(); for (Emp emp : empList) {     System.out.println("员工姓名:" + emp.getEname()); }    }    sqlSession.close();}