ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MyBatis多表关联查询:从一对一联表到一对多懒加载实战

MyBatis多表关联查询:从一对一联表到一对多懒加载实战 第一部分表间关系与数据视角1.1 全局关系 vs 单条数据视角⭐老师强调针对具体某条数据表间关系只有一对一或一对多两种。从单条记录看要么唯一对应另一张表里的单条信息一对一要么对应另一张表里的一堆信息一对多示例关系示例说明一对一学生 → 班主任张三唯一对应张老师一对多老师 → 学生张老师对应班里多个学生⭐老师强调判断时只需盯实际数据——一条数据对应一条、多条还是互多条不用管表名义上是什么。难点在于别把表整体关系和单条数据关系混淆。1.2 建模规范⭐老师强调数据库里一张表对应一个实体类不要为了省事把多个表合成一个实体。错误做法合成实体// ❌ 在学生类里硬塞老师字段违背职责单一 public class Student { private Integer id; private String name; // 硬塞teacher字段 private String tname; // 冗余 private String tphone; // 冗余 }⭐老师强调合成实体虽简单但会导致学生类冗余老师属性违背职责单一不推荐。规范做法应建关联映射。第二部分一对一关系association2.1 实体类设计Student实体类package com.qcby.entity; public class Student { private Integer id; private String name; private Integer age; private String sex; private Integer tid; /* 一对一关联一个Teacher对象 */ private Teacher teacher; Override public String toString() { return Student{ id id , name name \ , age age , sex sex \ , tid tid , teacher teacher }; } // getter/setter省略 }Teacher实体类package com.qcby.entity; public class Teacher { private Integer id; private String tname; // getter/setter、toString省略 }⭐老师强调一对一关系在一的一方Student加对象类型字段Teacher而不是拆散字段。2.2 方式一联表查询!-- 联表查询一次查出学生和老师 -- select idfindAll resultMapdemo select * from student,teacher where student.tid teacher.id /select resultMap iddemo typecom.qcby.entity.Student !-- 普通字段一一对应直接写 -- result propertyid columnid/ result propertyname columnname/ result propertyage columnage/ result propertysex columnsex/ result propertytid columntid/ !-- 特殊字段对象用association -- !-- property: 实体类中特殊字段的名字 -- !-- javaType: 特殊字段的类型 -- association propertyteacher javaTypecom.qcby.entity.Teacher result propertyid columnid/ result propertytname columntname/ /association /resultMap⭐老师强调普通字段直接映射一一对应特殊字段对象类型用associationproperty指实体类里要映射的属性名javaType指特殊字段的类型字段冲突两表都有id时框架只识别靠前的那个需注意或改名2.3 方式二分步查询!-- 分步查询先查学生再根据tid查老师 -- select idfindAll resultMapdemo select * from student /select resultMap iddemo typecom.qcby.entity.Student !-- 普通字段 -- result propertyid columnid/ result propertyname columnname/ result propertyage columnage/ result propertysex columnsex/ result propertytid columntid/ !-- 特殊字段分步查询 -- !-- select: 调用下一个查找的方法跨文件需写接口全类名.方法名 -- !-- column: 需要传输的字段名字把tid传过去 -- !-- fetchType: lazy延迟加载 / eager立即加载 -- association propertyteacher javaTypecom.qcby.entity.Teacher selectcom.qcby.dao.TeacherDao.getTeacherById columntid fetchTypelazy/ /resultMapTeacherDao接口package com.qcby.dao; import com.qcby.entity.Teacher; public interface TeacherDao { // 根据id查找老师的信息 Teacher getTeacherById(Integer id); }TeacherDao.xmlselect idgetTeacherById resultTypecom.qcby.entity.Teacher parameterTypejava.lang.Integer select * from teacher where id #{id} /select⭐老师强调同文件内直接写方法名跨文件调得用接口全类名加方法名column指定把主表哪个字段传过去当参数这就是N1查询——查N条学生触发N次老师查询第三部分一对多关系collection3.1 实体类设计Teacher实体类package com.qcby.entity; import java.util.List; public class Teacher { private Integer id; private String tname; /* 一对多一个老师对应多个学生 */ private ListStudent students; Override public String toString() { return Teacher{ id id , tname tname \ , students students }; } // getter/setter省略 }⭐老师强调一对多关系在一的一方Teacher加集合类型字段List用集合承载多的一端。3.2 方式一联表查询!-- 联表查询 -- select idgetTeachers resultMapdemo select * from teacher,student where teacher.id student.tid /select resultMap iddemo typecom.qcby.entity.Teacher result propertyid columnid/ result propertytname columntname/ !-- 特殊字段集合用collection -- !-- property: 特殊字段的名称 -- !-- ofType: 集合中泛型信息 -- collection propertystudents ofTypecom.qcby.entity.Student result propertyid columnid/ result propertyname columnname/ result propertysex columnsex/ result propertyage columnage/ result propertytid columntid/ /collection /resultMap⭐老师强调一对一用association对象一对多用collection集合property是集合字段名ofType指定集合的泛型类型如Student字段冲突两表都有id时teacher放前面只识别老师id学生id被覆盖需重命名避免3.3 方式二分步查询!-- 分步查询 -- select idgetTeachers resultMapdemo select * from teacher /select resultMap iddemo typecom.qcby.entity.Teacher result propertyid columnid/ result propertytname columntname/ !-- 特殊字段分步查询集合 -- !-- column: 把teacher的id传过去 -- !-- select: 调用查学生的方法 -- collection propertystudents ofTypecom.qcby.entity.Student columnid selectcom.qcby.dao.StudentDao.getStudentsByTeacherId/ /resultMapStudentDao新增方法package com.qcby.dao; import com.qcby.entity.Student; import java.util.List; public interface StudentDao { ListStudent findAll(); // 根据tid查找学生信息 ListStudent getStudentsByTeacherId(int tid); }StudentDao.xml新增select idgetStudentsByTeacherId parameterTypejava.lang.Integer resultTypecom.qcby.entity.Student select * from student where tid #{id} /select⭐老师强调分步查询先从teacher取记录拿到老师id再据tid去student表查对应学生。column指定把主表哪个字段传过去当参数。第四部分懒加载延迟加载4.1 全局配置configuration settings setting namelogImpl valueSTDOUT_LOGGING/ !-- 开启懒加载 -- setting namelazyLoadingEnabled valuetrue/ !-- 关闭侵入式懒加载改为按需加载 -- setting nameaggressiveLazyLoading valuefalse/ /settings environments defaultmysql !-- ... -- /environments mappers mapper resourcemapper/StudentDao.xml/ mapper resourcemapper/TeacherDao.xml/ /mappers /configuration4.2 懒加载 vs 立即加载fetchType说明lazy延迟加载用到时才查eager立即加载一并查出⭐老师强调lazyLoadingEnabledtrueaggressiveLazyLoadingfalse按需加载只取学生信息就不会去查关联的老师fetchType在association/collection上可单独设置懒加载本质是按需不是不查关联表而是等真正用到对应字段时才查效果对比场景立即加载懒加载只输出学生id也查老师不查老师输出学生老师名一起查用到时再查第五部分完整代码汇总5.1 一对一完整示例接口public interface StudentDao { ListStudent findAll(); }StudentDao.xmlmapper namespacecom.qcby.dao.StudentDao !-- 分步查询 -- select idfindAll resultMapdemo select * from student /select resultMap iddemo typecom.qcby.entity.Student result propertyid columnid/ result propertyname columnname/ result propertyage columnage/ result propertysex columnsex/ result propertytid columntid/ association propertyteacher javaTypecom.qcby.entity.Teacher selectcom.qcby.dao.TeacherDao.getTeacherById columntid fetchTypelazy/ /resultMap /mapper5.2 一对多完整示例接口public interface TeacherDao { Teacher getTeacherById(Integer id); ListTeacher getTeachers(); }TeacherDao.xmlmapper namespacecom.qcby.dao.TeacherDao !-- 单条查询 -- select idgetTeacherById resultTypecom.qcby.entity.Teacher parameterTypejava.lang.Integer select * from teacher where id #{id} /select !-- 分步查询一对多 -- select idgetTeachers resultMapdemo select * from teacher /select resultMap iddemo typecom.qcby.entity.Teacher result propertyid columnid/ result propertytname columntname/ collection propertystudents ofTypecom.qcby.entity.Student columnid selectcom.qcby.dao.StudentDao.getStudentsByTeacherId/ /resultMap /mapper附录一核心对比速查表association vs collection标签适用属性association一对一对象property、javaTypecollection一对多集合property、ofType联表查询 vs 分步查询对比联表查询分步查询查询次数1次N1次SQL复杂度高联表低单表配置复杂度高需映射所有字段低只配关联字段冲突需重命名无性能好一次查询差N1问题灵活度低高可懒加载fetchType 对比值说明lazy延迟加载用到才查eager立即加载一并查出
返回列表