当前位置: 首页 > news >正文

MyBatis:复杂结果集映射与分步查询

前言什么是 MyBatis 结果映射MyBatis 作为半自动化的 ORM 框架结果映射ResultMap是其最核心、最强大的功能。它的作用是自动将数据库查询返回的结果集字段映射到 Java 实体类属性解决数据库列名与实体属性不一致、多表关联数据封装、复杂对象嵌套等问题。在多表关联查询场景中普通的结果映射无法处理关联对象一对一、多对一和集合一对多因此需要使用association和collection标签实现复杂映射并可配合分步查询 延迟加载进一步提升性能。一、数据表结构与测试数据1. 学生表SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; DROP TABLE IF EXISTS student; CREATE TABLE student ( id int(11) NOT NULL AUTO_INCREMENT, Sname varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, sex varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, age int(11) DEFAULT NULL, t_id int(11) DEFAULT NULL, PRIMARY KEY (id) USING BTREE ) ENGINE InnoDB AUTO_INCREMENT 11 CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact; INSERT INTO student VALUES (1, 张三, 男, 18, 1); INSERT INTO student VALUES (2, 李四, 女, 18, 1); INSERT INTO student VALUES (3, 王五, 男, 18, 1); INSERT INTO student VALUES (4, 小白, 女, 18, 1); INSERT INTO student VALUES (5, 小黑, 男, 18, 1); INSERT INTO student VALUES (6, 小红, 女, 20, 2); INSERT INTO student VALUES (7, 小李, 男, 20, 2); INSERT INTO student VALUES (8, 小张, 女, 20, 2); INSERT INTO student VALUES (9, 小赵, 男, 20, 2); INSERT INTO student VALUES (10, 小王, 女, 20, 2); SET FOREIGN_KEY_CHECKS 1;代码解释创建学生表包含学生 id、姓名、性别、年龄、关联教师 id插入 10 条测试数据学生通过t_id关联老师。2. 老师表SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; DROP TABLE IF EXISTS teacher; CREATE TABLE teacher ( id int(11) NOT NULL AUTO_INCREMENT, Tname varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, PRIMARY KEY (id) USING BTREE ) ENGINE InnoDB AUTO_INCREMENT 3 CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact; INSERT INTO teacher VALUES (1, 张老师); INSERT INTO teacher VALUES (2, 李老师); SET FOREIGN_KEY_CHECKS 1;代码解释创建教师表包含教师 id、姓名插入 2 条测试数据作为学生表的关联表。二、一对一、多对一映射业务场景查询学生信息同时关联查询所属授课老师多个学生对应一个老师方式一嵌套结果联表查询实体类定义public class Student { private Integer id; private String Sname; private String sex; private Integer age; private Integer t_id; private Teacher teacher; // 关联老师对象实现多对一映射 } public class Teacher { private Integer id; private String Tname; }代码解释Student 类中添加 Teacher 对象用于接收关联查询的教师数据Teacher 类为普通实体类。Mapper 映射文件select idgetStudent1 resultMapStudentTeacher1 SELECT student.id,student.Sname,teacher.Tname FROM student LEFT JOIN teacher on student.t_id teacher.id /select resultMap idStudentTeacher1 typecom.qcby.entity.Student !-- 基础字段映射property实体属性column数据库列名 -- result propertyid columnid/ result propertySname columnSname/ result propertysex columnsex/ result propertyage columnage/ result propertyt_id columnt_id/ !-- association处理一对一/多对一的关联对象 -- association propertyteacher javaTypecom.qcby.entity.Teacher result propertyid columnid/ result propertyTname columnTname/ /association /resultMap代码解释编写LEFT JOIN联表 SQL一次性查询学生和老师数据resultMap自定义结果映射association封装 Teacher 对象。方式二分步查询实体类无需改动Mapper 映射文件!-- 第一步查询所有学生 -- select id getStudent resultMapStudentTeacher select * from student; /select !-- 结果映射关联第二步查询 -- resultMap idStudentTeacher typecom.qcby.entity.Student result propertyid columnid/ result propertySname columnSname/ result propertysex columnsex/ result propertyage columnage/ result propertyt_id columnt_id/ !-- select调用第二步查询的id column传递给第二步查询的参数学生的t_id -- association propertyteacher columnt_id javaTypecom.qcby.entity.Teacher selectgetTeacher/ /resultMap !-- 第二步根据id查询老师 -- select idgetTeacher resultTypecom.qcby.entity.Teacher select * from teacher where id #{t_id}; /select代码解释将复杂联表拆分为两条单表查询第一步查学生第二步根据学生的t_id查老师实现解耦。三、一对多映射业务场景查询老师信息同时获取名下所有学生一个老师对应多个学生方式一嵌套结果联表查询实体类定义public class Student { private Integer id; private String Sname; private String sex; private Integer age; private Integer t_id; } public class Teacher { private Integer id; private String Tname; private ListStudent students; // 学生集合实现一对多映射 }代码解释Teacher 类中添加ListStudent集合用于封装该老师名下的所有学生。Mapper 映射文件select idgetTeacher resultMapTeacherStudent SELECT teacher.id,teacher.Tname,student.Sname FROM teacher LEFT JOIN student on student.t_id teacher.id /select resultMap idTeacherStudent typecom.qcby.entity.Teacher result propertyid columnid/ result propertyTname columnTname/ !-- collection处理一对多的关联集合 -- !-- ofType指定集合中泛型的类型 -- collection propertystudents ofTypecom.qcby.entity.Student result propertySname columnSname/ /collection /resultMap代码解释联表查询老师和学生数据collection将重复的学生数据封装为 List 集合。方式二分步查询!-- 第一步查询所有老师 -- select idgetTeacher resultMapTeacherStudent2 select * from teacher /select !-- 结果映射关联第二步查询 -- resultMap idTeacherStudent2 typecom.qcby.entity.Teacher collection propertystudents columnid ofTypecom.qcby.entity.Student selectgetStudentByTeacherId / /resultMap !-- 第二步根据老师id查询学生 -- select idgetStudentByTeacherId resultTypecom.qcby.entity.Student select * from student where t_id #{t_id} /select代码解释第一步查老师第二步根据老师id查询对应学生通过collection实现一对多分步映射。四、MyBatis 延迟加载策略1. 策略作用联表查询一次性加载全部数据分步查询可配合延迟加载实现按需查询减少无效 SQL 执行优化性能仅分步查询支持。2. 全局配置settings !-- 开启延迟加载总开关 -- setting namelazyLoadingEnabled valuetrue/ !-- 关闭积极加载实现真正的按需加载 -- setting nameaggressiveLazyLoading valuefalse/ /settings代码解释在 MyBatis 核心配置文件中配置全局生效。3. 局部加载控制association propertyteacher columnt_id javaTypecom.qcby.entity.Teacher selectcom.qcby.dao.TeacherDao.getTeacher fetchTypelazy !-- lazy延迟加载eager立即加载 -- /代码解释fetchType优先级高于全局配置可单独控制某个关联的加载模式。4. 接口与映射补充// TeacherDao接口 Teacher getTeacher(Integer id);!-- TeacherDao.xml -- select idgetTeacher resultTypecom.qcby.entity.Teacher parameterTypejava.lang.Integer select * from teacher where id #{t_id}; /select代码解释定义教师查询接口供分步查询调用。5. 测试效果仅访问学生基础属性 →不触发老师查询Test public void getStudent(){ ListStudent student mapper.getStudent(); for (Student student1:student) { System.out.println(student1.getSex()); } }访问关联老师属性 →触发延迟查询Test public void getStudent(){ ListStudent student mapper.getStudent(); for (Student student1:student) { System.out.println(student1.getTeacher().getTname()); } }
http://www.zskr.cn/news/1373312.html

相关文章:

  • CentOS 7服务器管理员的福音:手把手配置fbterm终端,实现中英文无缝切换
  • 简历写“熟练Office”算造假?HR公认的真实标准,别再踩坑
  • 2026年蒸发式冷却塔怎么选:闭式冷却塔、不锈钢冷却塔、冷却塔填料、凉水塔、圆形冷却塔、横流式冷却塔、玻璃钢冷却塔选择指南 - 优质品牌商家
  • 2026双头超声波机厂家怎么选:非标订做超声波清洗机/伺服超声波/包布热压机/单头高周波机/双头高周波机/同步熔断机/选择指南 - 优质品牌商家
  • Ubuntu 22.04蓝牙开关秒关?别慌,先看dmesg日志里的这个Intel固件报错
  • 项目上传到gitee的两种方式,ssh和https
  • 面试题——全局邮件的设计
  • 从‘光程差为零’出发:手把手推导超透镜的相位公式(附Python验证代码)
  • 如何用pyTMD实现高精度潮汐预测:从入门到实战的完整指南
  • 用“挑西瓜”讲透《机器学习》第六章-支持向量机
  • Java内部类全解析:四种类型核心原理与实战理解
  • 腾讯云TRTC、声网、即构三款实时音视频SDK怎么选?2026实测对比
  • 2026高压发泡机技术解析:弹性体发泡机/方向盘高压泡机/水箱PU发泡机/热水器发泡机/热水器环戊烷发泡机/环戊烷发泡机/选择指南 - 优质品牌商家
  • 新电脑到手第一件事:关闭Windows 11/10的自动BitLocker加密(附详细路径图)
  • 保姆级教程:手把手教你用NVIDIA Surround搞定Prepar3D多屏显示(Win10/Win11通用)
  • 别再死记硬背!用Python代码和D-Separation定理,5分钟搞懂贝叶斯网络的4种基本结构
  • 位置编码——给序列安上坐标
  • 接入内网工具删除
  • 从Stata/R代码实操出发:手把手教你用双重差分法(DID)评估一个‘政策’的真实效果
  • 不只是编译:在龙芯3A4000的银河麒麟V10上,给FileZilla解决gnutls和wxWidgets依赖的完整思路
  • ARM SVE指令集:ST3B与ST3D存储指令详解
  • 企业级Gemini投资回报率坍塌预警:5个高危信号+2个紧急干预阈值,今日不查,下季度预算或被砍30%
  • Leetcode 剑指 Offer II 172. 统计目标成绩的出现次数
  • 想找适合孩子独自参加的北京研学,有没有师生配比高的好机构 - 品牌2025
  • 告别‘芝麻开门’:用Python和PyTorch搭建一个文本无关的声纹验证系统(附VoxCeleb数据集实战)
  • Ubuntu 20.04下,除了ntpd,你还可以试试chrony:一个更现代的时间同步方案配置指南
  • D-PHY
  • AI获客彻底迭代!2026年企业必须看懂的GEO智能流量新逻辑
  • 各个AI公司都在玩的Harness 架构:Harness架构深度解析
  • 基于 FreeRTOS + ESP8266(AT 指令)+ MQTT的实现方案