Mybatis07-Mybatis的高级映射及延迟加载

📅 2026/7/17 13:53:50
Mybatis07-Mybatis的高级映射及延迟加载
一、什么是高级映射MyBatis 的高级映射用于处理表之间的关联关系映射包括Java中的关系数据库关系MyBatis映射标签一个对象包含另一个对象一对一association一个对象包含对象集合一对多collection多个对象包含在一个对象中多对一二、多对一数据准备学生表t_stu班级表t_class一个班级对应多名学生通过cid作为外键。多的一方是学生一的一方是班级怎么分主表和副表原则谁在前谁是主表多对一多在前那么多的一方就是主表主表在jvm就是一个对象副表在jvm就是一个副对象主对象中包含副对象作为属性一对多一在前那么一的一方就是主表2-1、第一种方式一条 SQL级联属性映射字段拼成别名核心思想将多表联合查询出来的字段直接映射到嵌套对象的属性上。示例column对应的是sql中的列名缺点SQL 别名容易写错不易维护。2-2、第二种方式一条 SQL association显式配置对象映射核心思想用association标签显式描述clazz 对象如何映射。示例优点不需要起复杂别名支持更复杂嵌套❌缺点仍是一次性全加载不适合数据量大时延迟加载2-3、第三种方式两条 SQL association 分步查询推荐核心思想先查主表再查从表。MyBatis 在第一次查询后根据配置自动调用另一个select语句。例如Stu查询班级时延迟执行第二条查询。查询顺序1、先查询出t_stu的一条数据此时这条数据中有t_class 中的id2、根据查询出的cid从t_class表中查询出对应的clazz对象【示例1】StuMapper.xml【注意】association标签中的属性的含义property: Stu类中要查询的副类Clazz的属性名select: 通过哪一个id去执行sql语句column: 要执行的sql语句的传值是什么association就是告诉 MyBatis我这个对象里还包着另一个对象。ClazzMapper.xml【示例2】association就是告诉 MyBatis我这个对象里还包着另一个对象。比如你的Stu学生对象里有个clazz班级对象public class Stu { private Integer sid; private String sname; private Clazz clazz; // 学生属于一个班级这就是一对一关联 }2-3-1、select属性是干嘛的select属性的意思是你去执行另一个查询把结果塞到这里来。它实现的是分步查询也叫嵌套查询就是查两次第一步先查学生select idselectStudentById resultMapstudentResultMap SELECT sid, sname, cid FROM t_stu WHERE sid #{sid} /select第二步再查班级另一个独立的查询select idselectClassById resultTypeClazz SELECT cid, cname FROM t_class WHERE cid #{cid} /select第三步用association把两步连起来resultMap idstudentResultMap typeStu id propertysid columnsid/ result propertysname columnsname/ !-- 关键在这里 -- association propertyclazz columncid selectselectClassById/ !-- ↑ 这里的 select 就是上面第二步查询的 id -- /resultMap2-3-2、整个过程发生了什么当你调用selectStudentById(1)时MyBatis 会这样执行先执行主查询SELECT sid, sname, cid FROM t_stu WHERE sid 1查出来sid1, sname张三, cid101看到association里有select它发现columncid也就是用刚才查出来的cid101然后自动去执行selectClassById(101)执行子查询SELECT cid, cname FROM t_class WHERE cid 101查出来cid101, cname一班组装结果把子查询的结果封装成Clazz对象塞到Stu对象的clazz属性里select属性就是 MyBatis 的自动再去查一次功能。它让 MyBatis 在查到学生数据后自动拿着学生的cid再去查一次班级表然后把班级信息装到学生的clazz属性里。优点1、可复用2、充分利用延迟加载/懒加载机制。2-3-3、延迟加载用到的时候再查询不用的时候不查询。比如以上例子中只有在调用stu.getClazz()的时候才调用第二条查询语句selectById。作用提高性能。2-3-4、在mybatis中开启延迟加载1、局部设置局部设置只对当前association 关联的sql语句起作用默认没有开启延迟加载只看学生的名字的时候是不会查询t_class表的2、全局设置【注意】在实际开发中大部分都要延迟加载建议全局配置。若是有些sql有特殊需求不想用延迟加载配置如下2-4、三种方式对比总结实现方式查询次数特点是否支持懒加载推荐场景第一种级联别名1次简单直接靠列别名❌小型项目/快速开发第二种association1次清晰结构适合嵌套❌中等数据量第三种分步查询association select属性多次支持懒加载SQL 可复用✅大型系统、性能敏感场景 ✅✅✅三、一对多当前的pojo一对多有两种方式关联查询嵌套结果分步查询嵌套查询3-1、方式一一条 SQL collection标签联表查询一次性用联表JOIN把用户和订单都查出来。示例collection表示集合属性ofType表示集合中元素的类型✅ 优点一次 SQL 查出所有数据适合小到中等规模的数据❌ 缺点数据量大时会产生笛卡尔积造成重复浪费内存不支持懒加载3-2、方式二分步查询 collection select... /推荐也是我们常用的懒加载方式分两次执行 SQL。示例四、association VS collectionassociationcollection关系类型一对一一对多Java 属性单个对象如Clazz clazz集合如ListStudent stus查询结果1 条记录 → 1 个对象N 条记录 → Listselect 作用查一个关联对象查多个关联对象装进 List五、实战建议如果数据量小、结构简单 → 用JOIN嵌套结果如果集合数据多、结构复杂 → 用分步查询嵌套查询若希望优化性能 → 开启懒加载