Mybatis延迟加载

什么是延迟加载?

延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据,延迟加载也称懒加载。
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。


我们在上一篇文章的基础上进行延迟加载。
上一篇文章传送门:Mybatis一对一和多对多查询
由于使用的表过多,不使用延迟加载的情况下SQL语句较为复杂。
下面我们将通过延迟加载实现相同的效果。

开启延迟加载

我们需要在SqlMapConfig.xml的configuration中添加配置开启延迟加载

	<settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
		<!--开启日志打印-->
		<setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

修改IStudentDao接口

package dao;

import domain.Student;

import java.util.List;

public interface IStudentDao {

    List<Student> findAll();
	//根据课程ID查询学生
    Student findByc_id(Integer c_id);
}

编写IDetailsDao接口

package dao;

import domain.Details;


public interface IDetailsDao {
	// 根据学生ID查询详情信息
    Details findBys_id(Integer s_id);
}

修改ICourseDao接口

package dao;

import domain.Course;

import java.util.List;

public interface ICourseDao {

    List<Course> findAll();
	// 根据学生ID查询课程信息
    Course findBys_id(Integer s_id);
}

修改持久层接口的映射文件 IStudentDao.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">
<mapper namespace="dao.IStudentDao">
    <resultMap id="studentMap" type="student">
        <id  property="id" column="id"></id>
        <result property="name" column="s_name"></result>

        <association property="details" column="id" javaType="details" select="dao.IDetailsDao.findBys_id"></association>
        <collection property="courses" ofType="course" select="dao.ICourseDao.findBys_id" column="id"></collection>
    </resultMap>

    <!--配置查询所有-->
    <select id="findAll" resultMap="studentMap">
        select * from student
    </select>

    <select id="findByc_id" resultMap="studentMap">
       select * from student inner join (select student_id as s_id from stu_and_cou where course_id=#{c_id}) as tmp on tmp.s_id=id
    </select>
</mapper>

编写持久层接口的映射文件 IDetailsDao.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">
<mapper namespace="dao.IDetailsDao">
    <resultMap id="detailsMap" type="details">
        <id property="d_id" column="id"></id>
        <result property="s_id" column="s_id"></result>
        <result property="sex" column="sex"></result>
        <result property="age" column="age"></result>
    </resultMap>
    <select id="findBys_id" resultMap="detailsMap">
        select * from details where s_id=#{s_id}
    </select>
</mapper>

修改持久层接口的映射文件 ICourseDao.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">
<mapper namespace="dao.ICourseDao">

    <resultMap id="courseMap" type="course">
        <id property="c_id" column="c_id"></id>
        <result property="c_name" column="c_name"></result>
        <collection property="students" ofType="student" select="dao.IStudentDao.findByc_id" column="c_id"></collection>
    </resultMap>

    <!--配置查询所有-->
    <select id="findAll" resultMap="courseMap">
        select * from course;
    </select>

    <select id="findBys_id" resultType="Course">
      select * from course inner join (select course_id from stu_and_cou where student_id=#{s_id}) as e on e.course_id = c_id
    </select>
</mapper>

修改的内容就是这些了,运行测试代码可以实现相同的效果
当我们只需要每个学生的姓名时

	@Test
    public void teststudent()
    {
        IStudentDao studentDao = session.getMapper(IStudentDao.class);
        List<Student> students = studentDao.findAll();
        for (Student student : students) {
            System.out.println(student.getName());
        }
    }

在这里插入图片描述
可以看到仅执行了一次查询,关联的查询并没有执行。

当我们需要相关信息时

	@Test
    public void teststudent()
    {
        IStudentDao studentDao = session.getMapper(IStudentDao.class);
        List<Student> students = studentDao.findAll();
        for (Student student : students) {
            System.out.println("=============");
            System.out.println(student);
            System.out.println(student.getDetails());
            System.out.println(student.getCourses());
        }
    }

打印结果如下:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 841262455.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3224a577]
==>  Preparing: select * from student 
==> Parameters: 
<==    Columns: id, s_name, d_id
<==        Row: 1, 张三, 2
<==        Row: 2, 李四, 3
<==        Row: 4, 王五, 2
<==        Row: 5, 李华, 4
<==        Row: 6, 小明, 3
<==      Total: 5
=============
==>  Preparing: select * from details where s_id=? 
==> Parameters: 1(Integer)
<==    Columns: id, s_id, sex, age
<==        Row: 1, 1,, 19
<==      Total: 1
==>  Preparing: select * from course inner join (select course_id from stu_and_cou where student_id=?) as e on e.course_id = c_id 
==> Parameters: 1(Integer)
<==    Columns: c_id, c_name, course_id
<==        Row: 1, 专业英语, 1
<==        Row: 2, 英美文化, 2
<==      Total: 2
Student{id=1, name='张三'}
Details{id=1, s_id=1, sex='男', age=19}
[Course{c_id=1, c_name=专业英语}, Course{c_id=2, c_name=英美文化}]
=============
==>  Preparing: select * from details where s_id=? 
==> Parameters: 2(Integer)
<==    Columns: id, s_id, sex, age
<==        Row: 2, 2,, 20
<==      Total: 1
==>  Preparing: select * from course inner join (select course_id from stu_and_cou where student_id=?) as e on e.course_id = c_id 
==> Parameters: 2(Integer)
<==    Columns: c_id, c_name, course_id
<==        Row: 1, 专业英语, 1
<==      Total: 1
Student{id=2, name='李四'}
Details{id=2, s_id=2, sex='女', age=20}
[Course{c_id=1, c_name=专业英语}]
=============
==>  Preparing: select * from details where s_id=? 
==> Parameters: 4(Integer)
<==    Columns: id, s_id, sex, age
<==        Row: 3, 4,, 17
<==      Total: 1
==>  Preparing: select * from course inner join (select course_id from stu_and_cou where student_id=?) as e on e.course_id = c_id 
==> Parameters: 4(Integer)
<==    Columns: c_id, c_name, course_id
<==        Row: 3, c程序设计, 3
<==      Total: 1
Student{id=4, name='王五'}
Details{id=3, s_id=4, sex='男', age=17}
[Course{c_id=3, c_name=c程序设计}]
=============
==>  Preparing: select * from details where s_id=? 
==> Parameters: 5(Integer)
<==    Columns: id, s_id, sex, age
<==        Row: 5, 5,, 21
<==      Total: 1
==>  Preparing: select * from course inner join (select course_id from stu_and_cou where student_id=?) as e on e.course_id = c_id 
==> Parameters: 5(Integer)
<==    Columns: c_id, c_name, course_id
<==        Row: 4, linux基础, 4
<==        Row: 5, 文言文基础, 5
<==      Total: 2
Student{id=5, name='李华'}
Details{id=5, s_id=5, sex='女', age=21}
[Course{c_id=4, c_name=linux基础}, Course{c_id=5, c_name=文言文基础}]
=============
==>  Preparing: select * from details where s_id=? 
==> Parameters: 6(Integer)
<==    Columns: id, s_id, sex, age
<==        Row: 6, 6,, 18
<==      Total: 1
==>  Preparing: select * from course inner join (select course_id from stu_and_cou where student_id=?) as e on e.course_id = c_id 
==> Parameters: 6(Integer)
<==    Columns: c_id, c_name, course_id
<==        Row: 2, 英美文化, 2
<==      Total: 1
Student{id=6, name='小明'}
Details{id=6, s_id=6, sex='女', age=18}
[Course{c_id=2, c_name=英美文化}]
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3224a577]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3224a577]
Returned connection 841262455 to pool.

Process finished with exit code 0

可以看到进行了关联的查询。

关于Mybatis延迟加载的问题就分享到这了,希望大家能够有所收获,欢迎关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值