持续学习&持续更新中…
守破离
【Java从零到架构师第③季】【08】MyBatis-延迟加载
- 为什么要使用延迟加载
- 立即加载与延迟加载
- 立即加载
- 延迟加载
- MyBatis的延迟加载
- 实现延迟加载—需求一
- 实现延迟加载—需求二
- 全局延迟加载开关
- 注意和一些建议
- 参考
延迟加载:用到时 再加载
- 很多时候,我们是暂时用不上某个对象的所有属性的,特别是那些复杂庞大的属性
- 比如说,我现在只想知道Person对象的id和name,暂时使用不到Person对象的List
、List - 而使用之前的查询方法会将Person的所有信息都查出来,会造成极大的浪费
- 很多时候我们希望是在要用到某个对象的属性时(一般是集合collection类型的属性)才去加载它,而不是急着一次性的把它的所有信息都给搞出来
- 也就是说,先将简单的属性加载出来,那些复杂庞大的在要使用到它们的时候再去加载它们。
- 这时候就需要使用延迟加载技术了
- 一条SQL语句
- 可能会造成资源的浪费
- 如果不是集合类型、常用、比较小,可以考虑立即加载
- 多条SQL语句
- 这些SQL语句在不同的时机执行(被调用时执行。例:当person.getBankCards()时再去加载这个person对象的BankCard相关数据)
- 不会造成资源的浪费
- 如果是集合类型、不常用、比较大,建议延迟加载。
- 需求:通过Person的id查询出对应的Person对象,对这个Person对象的idCard、bankCards、jobs三个成员变量实现延迟加载
-
分析
- 既然要对Person对象的idCard、bankCards、jobs三个属性进行延迟加载 ,那么之前的SQL语句就需要修改,不能像之前那样一次性直接查询出所有内容
- 初始化查询时只需要查询出Person的id、name即可
- 当在Java中调用person.getIdCard()时,加载对应person对象的idCard;
- 当在Java中调用person.getBankCards()时,加载对应person对象的bankCards;
- 当在Java中调用person.getJobs()时,加载对应person对象的jobs;
- 这三个需要延迟加载的成员变量都需要通过对应person的id去单独的查询
- 那么这三个肯定要有属于自己的SQL查询语句
-
id_card.xml映射文件:
SELECT id, no, address FROM id_card WHERe person_id = #{personId}
- bank_card.xml映射文件:
- job.xml映射文件:
- person.xml映射文件:
实现延迟加载—需求二SELECT id, name FROM person
- 需求:通过Person的id查询出对应的Person对象,只对这个Person对象的bankCards、jobs两个成员变量实现延迟加载
-
分析
- 既然只对Person对象的bankCards、jobs这两个属性进行延迟加载
- 也就意味着初始化查询时需要查询出Person的id、name、idCard这三个属性
- 当在Java中调用person.getBankCards()时,加载对应person对象的bankCards;
- 当在Java中调用person.getJobs()时,加载对应person对象的jobs;
- 这两个需要延迟加载的成员变量都需要通过对应person的id去单独的查询
- 那么这两个肯定要有属于自己的SQL查询语句
-
bank_card.xml:
- job.xml:
- person.xml:
全局延迟加载开关SELECT person.id person_id, person.name person_name, id_card.id id_card_id, id_card.no id_card_no, id_card.address id_card_address FROM person JOIN id_card ON id_card.person_id = person.id
-
lazyLoadingEnabled默认为false
-
当某个关联对象配置了select属性时,是否延迟加载是可控制的:
- fetchType="lazy"时,延迟加载
- fetchType="eager"时,立即加载
-
aggressiveLazyLoading是配合lazyLoadingEnabled(延迟加载)使用的。
-
aggressiveLazyLoading:激进的延迟加载,默认值为false
- 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。
- 不开启时,每个延迟加载属性会按需加载。
- 使用IDEA的调试工具调试时、使用System.out直接打印MyBatis查询过来的对象时,看不出延迟加载效果
- 因此想要看出延迟加载效果只能使用System.out打印查询出来的对象的某个属性
- 如果在setting中配置了lazyLoadingEnabled为true的话,那么所有设置了select属性的关联对象都会默认开启延迟加载,就不用再写fetchType="lazy"属性了
- 如果想要某个设置了select属性的关联对象采取立即加载的方式加载数据,那么需要使用fetchType="eager"来覆盖掉默认的懒加载行为
- 如果不希望延迟加载,那么就像上面举例的那样,在查询“Person”的时候,就将其查询出来
- 如果希望延迟加载,那么就不要在查询“Person”的时候将其查出,而是再搞一个SQl语句(select标签),让其当要用到的时候再去查询。
小码哥-李明杰: Java从0到架构师③进阶互联网架构师.
本文完,感谢您的关注支持!



