06. mybatis 延迟加载

06. mybatis 延迟加载

当使用多表联合查询的时候,mybatis会根据需要查询的信息,判断是否可以开启延迟加载,来提高查询效率。

1、什么是延迟加载?

延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机。在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果。比如查询订单信息,并不一定需要及时返回订单对应的产品信息,查询商品分类信息并不一定要及时返回该类别下有哪些产品,这种情况一下需要一种机制,当需要查看时,再执行查询,返回需要的结果集,这种需求在Mybatis中可以使用延迟加载机制来实现。延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。

简而言之:

多表联合查询,根据你需要的结果信息,如果只是想要表1 的信息,那么表2 的查询sql语句就会先不执行。

2、启用延迟加载

Mybatis配置文件中通过两个属性lazyLoadingEnabled和aggressiveLazyLoading来控制延迟加载和按需加载。

lazyLoadingEnabled:是否启用延迟加载,mybatis默认为false,不启用延迟加载。lazyLoadingEnabled属性控制全局是否使用延迟加载,特殊关联关系也可以通过嵌套查询中fetchType属性单独配置(fetchType属性值lazy或者eager)。

aggressiveLazyLoading:是否按需加载属性,默认值false,lazyLoadingEnabled属性启用时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载,即使用到某关联属性时,实时执行嵌套查询加载该属性。

3、xml映射的建立

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">
    
<!--	
	namespace 指向对应接口的类路径	
 -->    

<mapper namespace="com.company.project.dao.EmpDao">
	<!-- 把重复的sql代码可以提炼出来,通过定义别名把sql列名和java属性对应 -->
	<sql id="selectResult">
		e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno,d.DNAME,d.LOC 
	</sql>
	
	
	<!-- 关闭延迟加载 -->
	<resultMap type="EmpPo" id="EmpResult1">
		<id property="empno" column="empno"/>
	 	<result property="ename"  column="ename"/>
	 	<result property="job"  column="job"/>
	 	<result property="mgr"  column="mgr"/>
	 	<result property="hiredate"  column="hiredate"/>
	 	<result property="sal"  column="sal"/>
	 	<result property="comm"  column="comm"/>
	 	<!-- 
	 		fetchType属性:lazy 开启延迟加载;eager 关闭延迟加载      
	 		-->
	 	<association property="deptPo" javaType="DeptPo" fetchType="eager"
	 	select="com.company.project.dao.EmpDao.findDeptById" column="deptno">
	 		
	 	</association>
	</resultMap>
	
	<!-- 开启延迟加载 -->
	<resultMap type="EmpPo" id="EmpResult2">
		<id property="empno" column="empno"/>
	 	<result property="ename"  column="ename"/>
	 	<result property="job"  column="job"/>
	 	<result property="mgr"  column="mgr"/>
	 	<result property="hiredate"  column="hiredate"/>
	 	<result property="sal"  column="sal"/>
	 	<result property="comm"  column="comm"/>
	 	<!-- 
	 		fetchType属性:lazy 开启延迟加载;eager 关闭延迟加载      
	 		-->
	 	<association property="deptPo" javaType="DeptPo" fetchType="lazy"
	 	select="com.company.project.dao.EmpDao.findDeptById" column="deptno">
	 		
	 	</association>
	</resultMap>
	
	<!-- 
	非延迟加载:直接将两个关联表的数据全部查询出来
	延迟加载(懒加载):使用某一个数据,才将其查询出来 
	-->
	<select id="findById1" parameterType="int" resultMap="EmpResult1">
		select
			e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno
		from 
			emp e
		where e.empno = #{empno}
	</select>
	
	<select id="findById2" parameterType="int" resultMap="EmpResult2">
		select
			e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno
		from 
			emp e
		where e.empno = #{empno}
	</select>

</mapper>

4、测试

EmpTest.java

package com.company.project.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.company.project.Po.EmpPo;
import com.company.project.dao.EmpDao;
import com.company.project.util.MyBatisUtil;

import junit.framework.TestCase;

public class EmpTest extends TestCase {

		//没有开启延迟加载,一次查询会把两个sql语句全部运行
		public void testFindById1() {
		try {
			SqlSession sqlSession = MyBatisUtil.getSqlSession();
			EmpDao empDao = sqlSession.getMapper(EmpDao.class);
			
			EmpPo empPo = empDao.findById3(7369);
			
			System.out.println(empPo.getEname());
			//当用到员工表的部门时,才会执行查询dept的sql语句
			System.out.println(empPo.getDeptPo().getDname());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			MyBatisUtil.closeSession();
		}
	}
	
	//开启延迟加载,会根据需要的结果数据来进行sql语句,如下:第一次只查询了emp表
	public void testFindById2() {
		try {
			SqlSession sqlSession = MyBatisUtil.getSqlSession();
			EmpDao empDao = sqlSession.getMapper(EmpDao.class);
			
			EmpPo empPo = empDao.findById3(7369);
			//只查询emp表
			System.out.println(empPo.getEname());
			//当用到员工表的部门时,才会执行查询dept的sql语句
			System.out.println(empPo.getDeptPo().getDname());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			MyBatisUtil.closeSession();
		}
	}
}

结果:

//没有开启延迟加载,testFindById1()的运行结果
[DEBUG] 2020-06-22 19:58:59,893 ==>  Preparing: select e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno from emp e where e.empno = ? 
[DEBUG] 2020-06-22 19:58:59,930 ==> Parameters: 7369(Integer)
[DEBUG] 2020-06-22 19:58:59,957 ====>  Preparing: select deptno,dname,loc from dept where deptno = ? 
[DEBUG] 2020-06-22 19:58:59,958 ====> Parameters: 20(Integer)
[DEBUG] 2020-06-22 19:58:59,960 <====      Total: 1
[DEBUG] 2020-06-22 19:58:59,962 <==      Total: 1
SMITH
RESEARCH


//开启延迟加载,testFindById2()的运行结果
[DEBUG] 2020-06-22 19:57:36,539 ==>  Preparing: select e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno from emp e where e.empno = ? 
[DEBUG] 2020-06-22 19:57:36,570 ==> Parameters: 7369(Integer)
[DEBUG] 2020-06-22 19:57:36,627 <==      Total: 1
SMITH
[DEBUG] 2020-06-22 19:57:36,631 ==>  Preparing: select deptno,dname,loc from dept where deptno = ? 
[DEBUG] 2020-06-22 19:57:36,632 ==> Parameters: 20(Integer)
[DEBUG] 2020-06-22 19:57:36,634 <==      Total: 1
RESEARCH

根据结果就可以开出开启延迟加载的作用,若开启,会根据需求来判断执行的sql语句,若不开启,则执行所有的sql语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值