注:代码已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,项目是mybatis-16-lazyload,需要自取,需要配置maven环境以及mysql环境(sql语句在resource下的test.sql中),觉得有用可以点个小星星。
docsify文档地址在:https://damaer.github.io/Mybatis-Learning/#/
mybatis的懒加载,也称为延迟加载,是指在进行关联查询的时候,按照设置延迟规则推迟对关联对象的select查询,延迟加载可以有效的减少数据库压力。延迟加载只对关联对象有延迟设置,主加载对象都是直接执行查询语句的
关联对象加载类型mybatis的关联对象的查询select语句的执行时机,可以分为3类,直接加载,侵入式加载与深度延迟加载。
1.直接加载执行完主加载对象的select语句,马上就会执行关联对象的select语句。
2.侵入式延迟加载执行对主加载对象的查询时,不会执行关联对象的查询,但是当访问主加载对象的详情时,就会马上执行关联对象的select查询,也就是说关联对象的查询执行,侵入到了主加载对象的详情访问中,可以理解为,将关联对象的详情侵入到主加载对象的详情中,作为它的一部分出现了。
3.深度延迟加载执行对主加载对象的查询的时候,不会执行对关联对象的查询,访问主加载对象的详情的时候,也不会执行关联对象的select查询,只有当真正的访问关联对象的详情的时候,才会执行对关联对象的select查询。
注意:延迟加载的最基本要求,关联对象的查询与主加载对象的查询必须是分别放在两个语句中的,不能使用多表连接查询,因为多表连接查询相当于把多张表连接成一张表的查询,无法做到分开查询,会一次性将表的内容查询出来。
延迟加载,可以应用到一对多,一对一,多对一,多对多的关联查询中。
举个例子:我们使用上一个demo,查询minister与country之间的关系,数据库如下:
#创建数据库 CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; #创建数据表 CREATE TABLE `test`.`student` ( `sid` INT(10) NOT NULL AUTO_INCREMENT ,`sname` VARCHAR(20) NOT NULL ,PRIMARY KEY(`sid`)) ENGINE = MyISAM; CREATE TABLE `test`.`course` ( `cid` INT(10) NOT NULL AUTO_INCREMENT ,`cname` VARCHAR(20) NOT NULL ,PRIMARY KEY(`cid`)) ENGINE = MyISAM; CREATE TABLE `test`.`middle` ( `id` INT(10) NOT NULL AUTO_INCREMENT ,`studentId` INT(10) NOT NULL ,`courseId` INT(10) NOT NULL ,PRIMARY KEY(`id`)) ENGINE = MyISAM; #初始化数据表 INSERT INTO `course` (`cid`, `cname`) VALUES ('1', 'JAVA') ; INSERT INTO `course` (`cid`, `cname`) VALUES ('2', 'C++') ; INSERT INTO `course` (`cid`, `cname`) VALUES ('3', 'JS') ; INSERT INTO `student` (`sid`, `sname`) VALUES ('1', 'Jam') ; INSERT INTO `student` (`sid`, `sname`) VALUES ('2', 'Lina') ; INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('1', '1', '1'); INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('2', '1', '2'); INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('3', '2', '1'); INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('4', '2', '3');与之对应的实体类:Country.class
public class Country { private Integer cid; private String cname; private Set<Minister> ministers; public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getName() { return cname; } public void setName(String cname) { this.cname = cname; } public Set<Minister> getMinisters() { return ministers; } public void setMinisters(Set<Minister> ministers) { this.ministers = ministers; } @Override public String toString() { return "Country [cid=" + cid + ", cname=" + cname + ", ministers=" + ministers + "]"; } }Minister.class:领导人实体类
public class Minister { private Integer mid; private String mname; @Override public String toString() { return "Minister [mid=" + mid + ", mname=" + mname + "]"; } public Integer getMid() { return mid; } public void setMid(Integer mid) { this.mid = mid; } public String getMname() { return mname; } public void setMname(String mname) { this.mname = mname; } }主配置文件mybatis.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置数据库文件 --> <properties resource="jdbc_mysql.properties"> </properties> <settings> <setting value="false"/> <!--<setting value="false"/>--> </settings> <!-- 别名,对数据对象操作全名太长,需要使用别名 --> <typeAliases> <!--<typeAlias type="bean.Student" alias="Student"/>--> <!--直接使用类名即可,对于整个包的路径配置(别名),简单快捷 --> <package/> </typeAliases> <!-- 配置运行环境 --> <!-- default 表示默认使用哪一个环境,可以配置多个,比如开发时的测试环境,上线后的正式环境等 --> <environments default="mysqlEM"> <environment> <transactionManager type="JDBC"> </transactionManager> <dataSource type="POOLED"> <property value="${jdbc.driver}"/> <property value="${jdbc.url}"/> <property value="${jdbc.user}"/> <property value="${jdbc.password}"/> </dataSource> </environment> </environments> <!-- 注册映射文件 --> <mappers> <mapper resource="mapper/mapper.xml"/> </mappers> </configuration>