为什么需要延迟加载
在涉及到关联查询中的一对多时,假设我们只需要获取“一“部分的数据,那么显然没有查询剩下来的多的必要。
比如,学生班级中有全班学生的信息,但是有时候我们查询班级仅仅是想获得班级的基本信息(班级编号之类的)而不关心班级的学生,这时就可以用到我们的延时加载(lazyLoad)。
延迟加载
延迟加载(也称按需加载或懒加载)是相对立即加载而言提出的。立即加载即不管数据需不需要都一并查询,而延迟加载是在你需要使用时才会去查询。
使用
配置conf.xml 文件
在setting中设置开启延迟加载
<settings>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 关闭立即加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载。
mapper.xml
<select id="queryStudentClassByClassId" parameterType="int" resultMap="class_student_lazyload_map">
select * from studentclass
<where>
classid=#{classid}
</where>
</select>
<resultMap type="entities.StudentClass" id="class_student_lazyload_map">
<id property="classid" column="classid"/>
<result property="classname" column="classname"/>
<!-- 延迟加载,当需要使用studens时才去调用这个SQL语句 -->
<collection property="students" ofType="entities.Student" select="mapper.StudentMapper.queryStudentByClassid" column="classid"></collection>
</resultMap>
mapper.StudentMapper.queryStudentByClassid
<select id="queryStudentByClassid" parameterType="int" resultType="entities.Student">
select * from student
<where>
classid = #{classid}
</where>
</select>
在association或者collection标签中,通过select属性指定子查询调用的SQL(值为namespace+id)。column属性指定将两个查询关联起来的字段值(通常为外键fk)
这里通过指定column字段为classid,这样在要用到第二个查询时,就会将调用第一个查询时传入的classid的值传给第二个SQL语句。
测试
public class testLazyLoad {
public static StudentClassMapper getStudentClassMapper() throws IOException {
Reader reader = Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
return session.getMapper(StudentClassMapper.class);
}
public static void main(String[] args) throws Exception {
StudentClassMapper studentClassMapper = getStudentClassMapper();
StudentClass stuClass = studentClassMapper.queryStudentClassByClassId(1);
System.out.println(stuClass.getClassid());
System.out.println(stuClass.getClassname());
//这里开始才使用到班级里的学生数据
List<Student> students = stuClass.getStudents();
for(Student s:students) {
System.out.println(s );
}
}
}
通过日志我们可以很清楚的看到加载延迟了: