什么是延迟加载?
延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据,延迟加载也称懒加载。
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
我们在上一篇文章的基础上进行延迟加载。
上一篇文章传送门: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延迟加载的问题就分享到这了,希望大家能够有所收获,欢迎关注。