所谓的 mybatis 延迟加载,指的是当进行多个表之间的关联查询时,先从单表中进行查询,按照一定的设计规则,需要时再对该表所关联的表单继续进行查询
好比如在某个购物网站上填写收货地址时,先加载省份,等用户选择了所在省份后,系统在关联加载处该省份下的城市
延迟加载最主要的一个作用就是减小了数据库的压力
三种不同的加载类型:
1:直接加载:当对一个表执行 select 语句时,马上对该表所关联的表执行 select 语句(将该表与该表所关联的表的数据直接查询出来)
2:侵入式延迟:当对一个表执行 select 语句时,不会对该表的关联表执行 select 查询,但当访问主加载对象的详情属性时,就会马上执行关联的select查询
3:深度延迟:当对一个表执行 select 语句时,不会对该表的关联表执行 select 查询,访问主加载对象的详情也不会对该表的关联对象执行 select 查询,只有当真正访问关联对象详情时,才会执行对关联对象的 select 查询
## 未设置延迟加载时的情况
1:创建mapper
<?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.doaoao.dao.TeamDao"> <!-- 根据teamid 查询team下的篮球队员 --> <select id="selectPlayerByTeamId" resultType="Player"> select id,name from t_player where tid=#{id} </select> <!-- 关系属性映射关系 --> <!-- 集合的数据来自 select 查询,该查询的条件是 selectTeamByIdAlone 查出的id --> <resultMap id="teamMapAlone" type="Team"> <id column="id" property="id"></id> <result column="name" property="name"></result> <collection property="playerList" ofType="Player" select="selectPlayerByTeamId" column="id"></collection> </resultMap> <select id="selectTeamByIdAlone" resultMap="teamMapAlone"> SELECT id,name FROM t_team where id=#{id} </select> </mapper>2:创建接口
package com.doaoao.dao; import com.doaoao.bean.Team; public interface TeamDao { Team selectTeamByIdAlone(int id); }3:创建测试类
@Test public void selectTeamByIdAlone() { Team team = teamDao.selectTeamByIdAlone(2); System.out.println(team); }4:执行后的数据分析
// 当未设置延迟加载时,查询主表后会查询该表所关联的表 // 第一条SQL 语句,查询表 t_team [DEBUG][2019-04-16 15:19:25]==> Preparing: SELECT id,name FROM t_team where id=? [DEBUG][2019-04-16 15:19:25]==> Parameters: 2(Integer) [TRACE][2019-04-16 15:19:25]<== Columns: id, name [TRACE][2019-04-16 15:19:25]<== Row: 2, huren // 第二条 SQL 语句,查询表 t_player [DEBUG][2019-04-16 15:19:25]====> Preparing: select id,name from t_player where tid=? [DEBUG][2019-04-16 15:19:25]====> Parameters: 2(Integer) [TRACE][2019-04-16 15:19:25]<==== Columns: id, name [TRACE][2019-04-16 15:19:25]<==== Row: 2, kobe [DEBUG][2019-04-16 15:19:25]<==== Total: 1 [DEBUG][2019-04-16 15:19:25]<== Total: 1 Team{id=2, name='huren'}## 设置延迟加载模式
在配置文件 mybatis.xml中(将下方的内容放在 properties和typeAliases之间)
<!-- 设置延迟加载 --> <settings> <!-- 设置延迟加载的总开关 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 侵入式延迟加载开关 --> <!-- 注意:3.4.1把那本之前value默认未true,之后版本默认未false --> <setting name="aggressiveLazyLoading" value="true" /> </settings>执行后的结果分析
// 只执行了一条 SQL 语句 [DEBUG][2019-04-16 15:47:33]==> Preparing: SELECT id,name FROM t_team where id=? [DEBUG][2019-04-16 15:47:33]==> Parameters: 2(Integer) [TRACE][2019-04-16 15:47:33]<== Columns: id, name [TRACE][2019-04-16 15:47:33]<== Row: 2, huren [DEBUG][2019-04-16 15:47:33]<== Total: 1
# 当将测试方法修改未如下配置时,会分别执行两条 SQL 语句
@Test public void selectTeamByIdAlone() { Team team = teamDao.selectTeamByIdAlone(1); System.out.println(team.getName()); }## 深度延迟加载
将 lazyLoadingEnabled 打开,将 aggressiveLazyLoading 关闭即可。
<!-- 设置延迟加载 --> <settings> <!-- 设置延迟加载的总开关 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 侵入式延迟加载开关 --> <!-- 注意:3.4.1把那本之前value默认未true,之后版本默认未false --> <setting name="aggressiveLazyLoading" value="true" /> </settings>当执行下方测试方法时,只执行一条SQL语句,因为没有使用到player相关数据
@Test public void selectTeamByIdAlone() { Team team = teamDao.selectTeamByIdAlone(1); System.out.println(team.getName()); }当执行下方测试方法时,执行两条SQL语句,因为使用到player相关数据
@Test public void selectTeamByIdAlone() { Team team = teamDao.selectTeamByIdAlone(1); // 使用到 player 的数据 System.out.println(team.getPlayerList().size()); }... 未完待续
本笔记参考自:小猴子老师教程 http://www.monkey1024.com