1.使用场景
一对一、一对多、多对一、多对多
例如:一对一:学生、学生证,一对多:班级——学生
如果不采用延迟加载(立即加载),查询时会将一和多都查询,班级、班级中的所有学生
如果想要暂时只查询一的一方,而多的一方先不查询,而是在需要的时候再去查询,就要用到延迟加载
2.一对一
(1)conf.xml
<settings>
<!-- 开启日志,并指定使用的具体日志 -->
<setting name="logImpl" value="LOG4J"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 关闭立即加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<mappers>
<!--如果增加了mapper.xml,要修改conf.xml配置文件(将新增的mapper.xml加载进去)-->
<mapper resource="nuc/hzb/mapper/studentMapper.xml" />
<mapper resource="nuc/hzb/mapper/studentCardMapper.xml" />
</mappers>
(2)studentMapper.xml
<resultMap type="student" id="student_studentcard_lazy">
<id property="stuNo" column="stuno"/>
<result property="stuName" column="stuname"/>
<result property="stuAge" column="stuage"/>
<!-- 学生证,通过select在需要的时候再查学生证 -->
<association property="studentCard" javaType="StudentCard" select="nuc.hzb.mapper.StudentCardMapper.queryCardById" column="cardid">
<!--
一对一时,对象成员使用association映射;javaType指定该属性的类型
此次采用延迟加载:在查询学生时,并不立即加载学生证信息
-->
</association>
</resultMap>
<select id="queryWithStudentWithOOLazy" resultMap="student_studentcard_lazy">
select * from student
</select>
(3)studentCardMapper.xml
<mapper namespace="nuc.hzb.mapper.StudentCardMapper">
<!-- 查询学生证信息 -->
<select id="queryCardById" parameterType="int" resultType="studentCard">
<!-- 查询学生对应的学生证 -->
select * from studentCard where cardid = #{cardId}
</select>
<!-- 根据cardid查询学生证的SQL:nuc.hzb.mapper.StudentCardMapper.queryCardById-->
</mapper>
(4)studentMapper.java
List<Student> queryWithStudentWithOOLazy();
(5)测试类
public static void queryWithStudentWithOOLazy() throws IOException {
Reader reader = Resources.getResourceAsReader("conf.xml") ;
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
studentMapper studentmapper = session.getMapper(studentMapper.class);
// 在该处打断点,debug
List<Student> students = studentmapper.queryWithStudentWithOOLazy();
for(Student student : students) {
System.out.println(student.getStuNo() + "," + student.getStuName() + "," + student.getStuAge());
System.out.println(student.getStudentCard());
}
session.close();
}
通过debug可以发现, 如果程序只需要学生,则只向数据库发送了查询学生的SQL
当我们后续需要用到学生证的时候,再第二次发送查询学生证的SQL
3.一对多
和一对一的延迟加载配置方法相同
(1)conf.xml
<settings>
<!-- 开启日志,并指定使用的具体日志 -->
<setting name="logImpl" value="LOG4J"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 关闭立即加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<mappers>
<!--如果增加了mapper.xml,要修改conf.xml配置文件(将新增的mapper.xml加载进去)-->
<mapper resource="nuc/hzb/mapper/studentMapper.xml" />
<mapper resource="nuc/hzb/mapper/studentCardMapper.xml" />
<mapper resource="nuc/hzb/mapper/studentClassMapper.xml" />
</mappers>
(2)studentClassMapper.xml
<!-- 类-表的对应关系 -->
<resultMap type="studentClass" id="class_student_lazyLoad_map">
<!-- 因为 type的主类是班级,因此先配置班级的信息-->
<id property="classId" column="classId"/>
<result property="className" column="className"/>
<!-- 配置成员属性学生,一对多;属性类型:javaType,属性的元素类型ofType -->
<!-- 再查班级对应的学生 -->
<collection property="students" ofType="student" select="nuc.hzb.mapper.studentMapper.queryStudentsByClassId" column="classid">
</collection>
</resultMap>
<!-- 一对多,带延迟加载 -->
<select id="queryClassAndStudents" resultMap="class_student_lazyLoad_map">
<!--先查询班级 -->
select c.* from studentclass c
</select>
(3)studentMapper.xml
<select id="queryStudentsByClassId" parameterType="int" resultType="student">
select * from student where classid = #{classid}
</select>
(4)studentClassMapper.java
List<StudentClass> queryClassAndStudents();
(5)测试类
// 查询班级和班级对应的学生,一对多(延迟加载)
public static void queryClassAndStudents() throws IOException {
Reader reader = Resources.getResourceAsReader("conf.xml") ;
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
studentClassMapper studentmapper = session.getMapper(studentClassMapper.class);
List<StudentClass> studentClassList = studentmapper.queryClassAndStudents();
for(StudentClass studentClass : studentClassList) {
System.out.println(studentClass.getClassId() + studentClass.getClassName());
for (Student student : studentClass.getStudents()) {
System.out.println(student);
}
}
session.close();
}
4.延迟加载的步骤
(1)开启延迟加载
配置conf.xml,通过settings标签
(2)配置mapper.xml
需要两个mapper.xml映射文件
学生、学生证
班级、学生
(3)例如
先查班级再查学生
查询班级通过resultMap标签去配置映射关系
查询学生的sql是通过select属性指定,并且通过column指定外键