Mybatis 学习(五)——延迟加载与分步查询
作者:互联网
文章目录
本篇博客主要讲的是延迟加载,也叫懒加载,但是懒加载往往与分布查询同时使用,作为背景知识我们也介绍一下分布查询
一、分步查询
分布查询通常应用于关联表查询,通常我们关联查询是进行多表联合查询,分布查询时先查询主表,然后通过主表得到的信息将参数传递给关联表,查询关联表的信息。
从代码层面上来说:
关联表能简化代码编写逻辑,减小代码编写难度
从功能层面上来说:关联表只需要查询一次数据库,对于业务量小的系统来说效率更高,数据库压力更小
分布查询对染需要多次查询数据,但是这也意味着能够更好的使用数据缓存服务,且缓存的数据耦合度低,利用率高,单词查询效率很高,对于业务量大的系统来说数据库压力较小
分布查询的实现
需求:通过分布查询查询学生信息
下面这两个类是我们今天使用的例子,Student 类里面有一个Dept 的对象,我们通过分布查询来得到学生的信息。
public class Student {
private Integer id;
private String name;
private String passward;
private Dept dept;
public Student(){
}
public Student(Integer id ,String name,String passward) {
this.id = id;
this.name = name;
this.passward = passward;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Student(Integer id , String name, String passward, Dept dept) {
this.id = id;
this.name = name;
this.passward = passward;
this.dept = dept;
}
public Dept getDept() {
return dept;
}
public void setDid(Dept dept) {
this.dept = dept;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPassward() {
return passward;
}
public void setPassward(String passward) {
this.passward = passward;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", passward='" + passward + '\'' +
'}';
}
public class Dept {
private Integer id;
private String name;
private List<Student> stus;
public Dept(){}
public Dept(Integer id,String name) {
this.id = id;
this.name = name;
}
public Dept(Integer id){
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Student> getStus() {
return stus;
}
public void setStus(List<Student> stus) {
this.stus = stus;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
第一步:我们在dao层定义两个接口
/**
* 通过id查学生信息,分步查询
* @param id
* @return
*/
public Student getStuByIdStep(Integer id);
/**
* 通过id查出Dept 信息
* @param id
* @return
*/
public Dept getDeptByIdPlus(Integer id);
第二步:编写对应的映射文件
<resultMap id="MystudentStep" type="com.tulun.bean.Student">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="passward" property="passward"></result>
<!--
association:定义关联对象的封装规则
select:表明当前属性是调用select 指定的方法查出的结果
column:指定将哪一列的值传给这个方法
流程:使用select 指定的方法(传入column 指定的这列参数的值)查出对象,
并封装给property 指定的属性
-->
<association property="dept"
select="com.tulun.dao.DeptMapper.getDeptById"
column="d_id">
</association>
</resultMap>
解释一下association 里面的属性
属性 | 作用 |
---|---|
select | 表示当前是调用select 指定的方法查询结果 |
property | 将select 查询得到的结果封装给主表的哪个属性 |
column | 将主表的哪一列传给这个属性 |
流程:使用select 指定的方法,传入的参数是column指定的参数,将查询的结果封装给property 指定的属性
第三步:编写查询的SQL文件
<select id="getStuByIdStep" resultMap="MystudentStep">
select * from student where id = #{id}
</select>
<select id="getDeptById" resultType="com.tulun.bean.Dept">
select * from dept where id = #{id}
</select>
第四步:单元测试
@Test
public void stepTest(){
StudentMapperPlus mapper = session.getMapper(StudentMapperPlus.class);
Student stu = mapper.getStuByIdStep(1);
}
从打印的日志可以看出和关联查询不同的是这里发送了两条SQL语句到数据库
我们总结一下整个过程
- 通过我们传入的id查询主表(Student)
- 主表哦查询的信息有一列是d_id ,表示的是部门id,把这个d_id 传入关联表(Dpet),得到关联的对象的信息
二、延时加载
MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。
Mybatis 根据关联对象查询Select 语句的查询时机分为直接加载、侵入式加载、深度延迟性加载
1.直接加载
执行完主加载对象的select语句,马上执行关联对象的Select语句
2.侵入式加载
执行完主加载对象查询后不会马上执行关联对象查询,但是当访问主加载对象时,就会加载关联对象的查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。
深度延迟加载
执行主对象的查询时不会执行关联对象的执行,访问主对象详情时也不会执行关联对象的查询,只有当访问关联对象时才会对其进行查询
上面那个例子中,我们有时候暂时不需要dept 的信息,或者根本就不需要dept的信息,但是按照原来的方法也就是立即加载,也就是直接加载
这三种加载方式的切换只要设置配置文件的两个属性就好
直接加载
配置文件
<!-- 延时加载 -->
<setting name="lazyLoadingEnabled" value="false"/>
<!--侵入式加载-->
<setting name="aggressiveLazyLoading" value="false"/>
注意:当lazyLoadingEnabled 设置为false ,aggressiveLazyLoading 是不起作用的
@Test
public void stepTest(){
StudentMapperPlus mapper = session.getMapper(StudentMapperPlus.class);
Student stu = mapper.getStuByIdStep(1);
}
侵入式加载
侵入式加载分为两种情况
设置配置文件
<!-- 延时加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--侵入式加载-->
<setting name="aggressiveLazyLoading" value="true"/>
1.当我们不访问主对象时
2.当我们访问主对象时
@Test
public void stepTest(){
StudentMapperPlus mapper = session.getMapper(StudentMapperPlus.class);
Student stu = mapper.getStuByIdStep(1);
System.out.println(stu);
}
访问主对象的时候可以看到关联对象查询也被执行
深度延迟加载
设置配置文件
<!-- 延时加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--侵入式加载-->
<setting name="aggressiveLazyLoading" value="false"/>
1.当不访问关联对象,仅仅访问主对象,关联对象的查询不被执行
@Test
public void stepTest(){
StudentMapperPlus mapper = session.getMapper(StudentMapperPlus.class);
Student stu = mapper.getStuByIdStep(1);
System.out.println(stu);
}
2.当访问关联对象的时候,关联对象的查询才会被执行
@Test
public void stepTest(){
StudentMapperPlus mapper = session.getMapper(StudentMapperPlus.class);
Student stu = mapper.getStuByIdStep(1);
System.out.println(stu.getDept());
}
访问了两次数据库
fetchType 参数
<association property="dept"
fetchType="lazy"
select="com.tulun.dao.DeptMapper.getDeptById"
column="d_id">
</association>
fetchType是association 下的一个子参数,局部方法可知指定加载形式,是懒加载还是积极加载它有值可以为lazy 或者是eager,lazy 表示懒加载,eager 表示延迟加载。
当设置了fetchType参数以后,以这个参数为标准,全局配置的不起作用
标签:name,id,String,分步,Mybatis,查询,public,加载 来源: https://blog.csdn.net/Alyson_jm/article/details/92393301