什么情况下需要延迟加载

在上一讲中有如下JavaBean类

  1. public class Person {
  2. private Integer id;
  3. private String name;
  4. private Integer age;
  5. private IdCard idCard;
  6. private List<BankCard> bankCards;
  7. private List<Role> roles;
  8. //setter getter。。。
  9. }

可以通过如下SQL语句查询出Person的所有信息。

  1. SELECT
  2. person.* ,
  3. id_card.`no` AS id_no,id_card.address,
  4. bank_card.id AS bank_card_id,bank_card.`no` AS bank_card_no,bank_card.amount ,
  5. role.`name` AS role_name,role.duty
  6. FROM person JOIN id_card ON person.id = id_card.person_id
  7. LEFT JOIN bank_card ON person.id = bank_card.fn_person_id
  8. LEFT JOIN person_role ON person.id = person_role.person_id
  9. LEFT JOIN role ON role.id = person_role.role_id

这样做从业务功能的角度是没有问题的。但如果我们只用到Person的姓名和年龄,这时我们仍然要关联查询身份证表、银行卡表、角色表。关联这么多表查询效率就会降低很多,并且查询出来的数据都要在内存里面。如果我们能办到需要什么数据再查什么数据,也就是懒加载,就会大大提高查询效率和节省内存使用。

懒加载的使用

我们可以根据情况对association、collection标签进行懒加载。通常的情况是对列表进行懒加载也就是对应的collection标签。比如上面Person类的银行卡信息、角色信息等。

使用方式

我们对上面的查询进行懒加载处理,比如对身份证信息、银行卡信息、角色信息进行懒加载。
需要在延迟加载的association、collection标签中新增如下3个字段:

  • fetchType 有两个取值:(1)lazy : 懒加载 (2)eager :立即加载
  • select :当懒加载时,执行的查询的ID(namespace + 语句的ID)。
  • column:�执行select语句时传递的参数

MyBatis对应的mapper

  1. <select id="getPersonAllInfoLazy" resultMap="allInfoLazy">
  2. SELECT
  3. person.*
  4. FROM person where id = #{id}
  5. </select>
  6. <resultMap id="allInfoLazy" type="com.lff.beans.Person">
  7. <id property="id" column="id" />
  8. <result property="name" column="name" />
  9. <result property="age" column="age" />
  10. <association property="idCard" javaType="com.lff.beans.IdCard" fetchType="lazy" column="id" select="person.fetchIdCard"/>
  11. <collection property="bankCards" ofType="com.lff.beans.BankCard" fetchType="lazy" column="id" select="person.fetchBankCards" />
  12. <collection property="roles" ofType="com.lff.beans.Role" fetchType="lazy" column="id" select="person.fetchRolesLazy"/>
  13. </resultMap>
  14. <!-- 根据person_id查询身份证-->
  15. <select id="fetchIdCard" parameterType="int" resultType="com.lff.beans.IdCard">
  16. SELECT id_card.* FROM id_card WHERE id_card.person_id = #{id}
  17. </select>
  18. <!-- 根据person_id查询身所有的银行卡-->
  19. <select id="fetchBankCards" parameterType="int" resultMap="bankCardLazyMap">
  20. SELECT bank_card.`no` AS bank_card_no,bank_card.amount amount FROM bank_card WHERE bank_card.fn_person_id = #{id}
  21. </select>
  22. <resultMap id="bankCardLazyMap" type="com.lff.beans.BankCard">
  23. <!-- 这里的属性property都是类BankCard的属性名,column是数据库查询出来的字段-->
  24. <result property="no" column="bank_card_no" />
  25. <result property="amount" column="amount" />
  26. </resultMap>
  27. <!-- 根据person_id查询角色-->
  28. <select id="fetchRolesLazy" resultType="com.lff.beans.Role">
  29. SELECT role.* FROM role JOIN person_role ON role.id = person_role.role_id AND person_role.person_id = #{id}
  30. </select>

可以在MyBatis核心配置文件中设置lazyLoadingEnabled 这样上面的fetchType选项可以省略。
延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。

  1. <setting name="lazyLoadingEnabled" value="true"/>