07 MyBatis之高级映射 + 懒加载(延迟加载)+缓存
1. 高级映射
例如有两张表, 分别为班级表和学生表
自然, 一个班级对应多个学生
像这种数据 , 应该如果如何映射到Java的实体类上呢? 这就是高级映射解决的问题
以班级和学生为例子 , 因为一个班级对应多个学生 , 因此学生表中必定有一个班级编号字段cid
但我们在学生的实体类中不需要加入这个字段, 而是通过另一个方法实现一对多映射/多对一映射
1.1 高级映射的分类
-
关联映射(Association Mapping)
关联映射用于处理对象之间的一对一关系。例如,一个订单对象可能包含一个关联的客户对象。通过使用 MyBatis 的关联映射,你可以在查询订单的同时,自动填充每个订单所关联的客户信息。 -
集合映射(Collection Mapping)
集合映射用于处理一对多关系。例如,一个客户可能有多个订单。在 MyBatis 中,你可以定义映射规则来自动将客户的所有订单作为一个集合属性加载到客户对象中。
1.2 前置知识
如何区分主表和副表?
原则: 谁在前谁就是主表
例如
多对一: 多(学生)在前, 多(学生)就是主表
一对多: 一(班级)在前, 一(班级)就是主表
1.2 多对一关系的实现
首先 既然是多(学生)对一(班级)关系 , 此时学生是主表(主对象),
那么学生实体类中应当加入班级对象的声明
private Clazz clazz;
1.2.1 多对一映射的第一种方式 一条SQL语句 , 级联属性映射
仅在studentMapper接口中声明一个方法
<!--id为"studentResultMap"的resultMap的数据 , 按照以下规则映射到实体上 -->
<resultMap id="studentResultMap" type="student"/><!--主键映射 -->
<id property="sid" column="sid"/>
<result property="sname" column="sname"/><!--嵌套的班级对象映射 -->
<result property="clazz.cid" column="cid"/>
<result property="clazz.cname" column="cname"/>
</resultMap><!--id为"selectById"的查询语句, 查询结果放到id为"studentResultMap"的resultMap中 -->
<select id="selectById" resultMap="studentResultMap">selects.sid,s.sname,c.cid,c.cnamefrom <!--多表连接, 主表在前 -->t_student s left join t_clazz c on s.cid= c.cidwheres.sid={sid}
</select>
测试
sout(student.getSid());
sout(student.getClazz().getCid());
sout(student);
1.2.2 多对一映射的第二种方式 , 一条SQL语句 , 采用association标签
在StudentMapper中定义一个新接口方法
Student selectByIdAssociation(Integer id);
<!--id为"studentResultMapAssociation"的resultMap的数据 , 按照以下规则映射到实体上 -->
<resultMap id="studentResultMapAssociation" type="student"/><!--主键映射 -->
<id property="sid" column="sid"/>
<result property="sname" column="sname"/><!--班级属性映射采用Association标签. 一个Student对象关联一个Clazz对象
property指定映射的具体对象 -->
<association property="clazz" javaType="com.sunsplanter.pojo.Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/>
</association></resultMap><!--id为"selectByIdAssociation"的查询语句, 查询结果放到id为"studentResultMapAssociation"的resultMap中 -->
<select id="selectByIdAssociation" resultMap="studentResultMapAssociation">selects.sid,s.sname,c.cid,c.cnamefrom <!--多表连接, 主表在前 -->t_student s left join t_clazz c on s.cid= c.cidwheres.sid={sid}
</select>
1.2.3 多对一映射的第三种方式 两条SQL语句 ,分步查询
常用 优点是可复用, 且支持懒加载
基本思路是: 既然是多对一, 那么先查询多(学生)的信息, 从中拿到cid , 然后再用cid另外查询一次班级表
两条SQL语句自然要有两个接口方法 ,分别位于StudentMapper和ClazzMapper中
public interface StudentMapper{//分布查询的第一步, 先根据学生的sid查出学生信息 Student selectByIdStep1(Integer sid);}public interface ClazzMapper{//分布查询的第一步, 先根据学生的sid查出学生信息 Clazz selectByIdStep2(Integer cid);}
两个mapperxml文件分别为
<!--id为"studentResultMapAssociation"的resultMap的数据 , 按照以下规则映射到实体上 -->
<resultMap id="studentResultMapByStep" type="com.sunsplanter.pojo.Student"/>
<!--主键映射-->
<id property="sid" column="sid"/>
<result property="sname" column="sname"/><!--班级属性映射采用Association标签. 一个Student对象关联一个Clazz对象
property指定映射的具体对象 -->
<association property="clazz" ><id property="cid" column="cid"/><!--指定第二步SQL语句的ID --><!--将cid字段作为查询传入第二步SQL语句--><select="com.sunsplanter.mapper.ClazzMapper.selectByIdStep2"><column="cid">
</association>
</resultMap><select id="selectByIdStep1" resultMap="studentResultMapByStep">selectsid, sname cid from t_studen where sid = #{sid}
</select>
<!--由于查询的结果与实体属性完全一致, 不需要再写resultMap标签进行结果映射--><select id="selectByIdStep2" resultType="com.sunsplanter.pojo.Clazz">selectcid,cname from t_clazz where cid = #{cid}
</select>
测试结果: 可以发现确实是先查了学生的信息得到cid, 再以cid去查班级信息 ,最终拼接起来输出的

1.2.4 多对一的懒加载
表连接里有一个概念叫笛卡尔积.
越多的表越多的匹配次数.
通过在association标签中增加fetchType="lazy"属性来开启懒加载
或在mybati config文件中的全局的setting标签中开启
<settings>
<setting name="lazyLoadingEnabled" value="true/">
</settings>
实际开发中往往是这样:
先在全局开启懒加载 , 对于特定需要全部加载的语句
通过在association标签中增加fetchType="eager"属性来关闭懒加载
1.2.5 测试
在上例中 , 假如我们没有开启懒加载
此时我们只需要完整的学生信息.
sout(Student);
仍会执行两条语句, 查询两张表, 即使根本没用到第二张表
开启懒加载后 , 便只会执行第一条selectByIdStep1的SQL语句
1.3 一对多关系的实现
需求: 根据班级ID查询指定班级下的所有学生信息
一(班级)对多(学生) , 因此班级是主表
一对多的实现 ,通常是在一(班级)的一方声明一个List集合属性
在班级类中增加
private List<Student> stus;
1.3.1 一对多映射的第一种实现 collection
与多对一并无本质区别, 核心是resultMap标签中的association标签换为collection标签
<!--id为"clazzResultMap"的resultMap的数据 , 按照以下规则映射到实体上 -->
<resultMap id="clazzResultMap" type="com.sunsplanter.pojo.clazz"/>
<!--主键映射-->
<id property="cid" column="cid"/>
<result property="cname" column="cname"/><!-- property属性指定Clazz实体类中定义的List的名称 , ofType指定Clazz实体类中定义的List中的存储对象-->
<collection property="stus" ofType="com.sunspalnter.pojo.Student" ><id property="sid" column="sid"/><result property="sname" column="sname"/>
</collection>
</resultMap>
测试结果, 可以看到班级表(主表)左外连接学生表

1.3.2 一对多映射的第一种实现 分步查询
<!--id为"clazzResultMapStep"的resultMap的数据 , 按照以下规则映射到实体上 -->
<resultMap id="clazzResultMapStep" type="com.sunsplanter.pojo.clazz"/>
<!--主键映射-->
<id property="cid" column="cid"/>
<result property="cname" column="cname"/><!-- property属性指定Clazz实体类中定义的List的名称 , ofType指定Clazz实体类中定义的List中的存储对象-->
<collection property="stus" <!--select指定第二步的SQL语句ID , column指定将cid字段作为参数传入第二步-->select="com.sunsplanter.mapper.StudentMapper.selectByCidStep2" column="cid"/>
</resultMap><select id="selectByIdStep1" resultMap="clazzResultMapStep">selectcid,cname from t_clazz where cid = #{cid}
</select>
<select id="selectByCidStep2" resultType="com.sunsplanter.pojo.Student">selectsid,sname from t_student where sid = #{sid}
</select>
测试结果

1.4 多对多和一对一
多对多实际就是分解为两个一对多
2. 缓存
缓存的作用: 通过减少IO的方式,来提高程序的执行效率
常用的缓存技术有: 字符串常量池 , 整型数常量池 , 线程池 , 连接池
mybats的缓存存:将select语的查询结果放到到缓存(内存)
下次还是这条select的话,直接从缓存(内存)中取,不再从外存中查.
mybatis缓存包括:
- 一级缓存:将查询到的数据存储到SqlSession中。
- 二级缓存:将查询到的数据存储到SqlSessionFactory中 , 缓存空间更大
- 或者集成其它第三方的缓存: 比如EhCache[Java语言开发的]、Memcache[C语言开发的]
缓存只针对于DQL语句,也就是说缓存机制只对应select语句.
2.1 一级缓存
一级缓存默认是开启的。不需要做任何配置
2.1.1 一级缓存生效
原理:只要使用同一个SqlSession对象执行同一条SQL语句,就会走缓存
可以看到 ,当使用同一个sqlSession对象执行相同的SQL语句时, 后台实际只执行了一次, 却输出了两条结果


2.1.1 一级缓存失效
- sqlSession对象不是同一个肯定不走缓存
- 查询条件不一样肯定不走缓存
- 即使上述同时两个条件, 如果在第一次DQL和第二次DQL之间发生以下两件事情的任意一件, 会令缓存清空
a. 执行了sqlSession的clearCache()方法 , 这会手动清空一级缓存
b. 执行了INSERT/DELETE/UPDATE任意一个语句时 , 不管是操作哪张表 都会直接清空一级缓存(思想是避免修改了数据后 , 输出缓存中的假数据)
2.2 二级缓存
2.2.1 二级缓存生效
使用二级缓存必须同时具备以下条件
2.2.1 二级缓存失效
相关文章:
07 MyBatis之高级映射 + 懒加载(延迟加载)+缓存
1. 高级映射 例如有两张表, 分别为班级表和学生表 自然, 一个班级对应多个学生 像这种数据 , 应该如果如何映射到Java的实体类上呢? 这就是高级映射解决的问题 以班级和学生为例子 , 因为一个班级对应多个学生 , 因此学生表中必定有一个班级编号字段cid 但我们在学生的实体…...
MT8791迅鲲900T联发科5G安卓核心板规格参数_MTK平台方案定制
MT8791安卓核心板是一款搭载了旗舰级配置的中端手机芯片。该核心板采用了八核CPU架构设计,但是升级了旗舰级的Arm Cortex-A78核心,两个大核主频最高可达2.4GHz。配备了Arm Mali-G68 GPU,通过Mali-G88的先进技术,图形处理性能大幅提…...
java:Java中的数组详解
目录 Java数组的定义和特点: Java数组的初始化和赋值 Java数组的常用操作 1. 遍历数组 2. 获取数组长度 3. 访问数组元素 4. 数组的拷贝 多维数组 数组的排序和查找 冒泡排序: 快速排序 : 二分查找: 数组的应用: Java数…...
Modern C++ std::visit从实践到原理
前言 std::visit 是 C17 中引入的一个模板函数,它用于对给定的 variant、union 类型或任何其他兼容的类型执行一个访问者操作。这个函数为多种可能类型的值提供了一种统一的访问机制。使用 std::visit,你可以编写更通用和灵活的代码,而无需关…...
谷歌gemma2b windows本地cpu gpu部署,pytorch框架,模型文件百度网盘下载
简介 谷歌DeepMind发布了Gemma,这是一系列灵感来自用于Gemini相同研究和技术的开放模型。开放模型适用于各种用例,这是谷歌非常明智的举措。有2B(在2T tokens上训练)和7B(在6T tokens上训练)模型,包括基础和指令调整版本。在8192个token的上下文长度上进行训练。允许商业使…...
数据结构-查找与排序
数据结构再往后就是比较零散的各种操作,查找与排序是其中最常出现的,今天来总结一下常用的查找与排序所用的方法 查找 顺序查找 最简单的查找方式,遍历,然后比较 bool search1(int *a,int n,int k){for (int i1;i<n;i){//遍…...
【前端素材】推荐优质后台管理系统Qovex平台模板(附源码)
一、需求分析 1、定义 后台管理系统是一种用于管理和监控网站、应用程序或系统的在线工具。它通常是通过网页界面进行访问和操作,用于管理网站内容、用户权限、数据分析等。后台管理系统是网站或应用程序的控制中心,管理员可以通过后台系统进行各种管理…...
MATLAB环境下基于短时傅里叶变换和Rényi熵的脑电信号和语音信号分析
傅里叶变换是不能很好的反映信号在时域的某一个局部范围的频谱特点的,这一点很可惜。因为在许多实际工程中,人们对信号在局部区域的特征是比较关心的,这些特征包含着十分有用的信息。这类信号因为在时域(或者是空间域)上具有突变的非稳定性和…...
Go语言调用身份证实名认证API方法-标准版身份证实名认证接口
翔云身份证实名认证接口具备高准确度的身份信息比对能力,包括姓名、身份证号码、人脸照片等信息的一致性验证,并能实时反馈验证结果。 以下是GO语言调用翔云身份实名认证API的代码: package mainimport ("fmt""bytes"&q…...
数据库增删改查
DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段)DML: 数据操作语言,用来对数据库表中的数据进行增删改DQL: 数据查询语言,用来查询数据库中表的记录DCL: 数据控制语言,用来创建数据库用户、控制数…...
10.CSS3的calc函数
CSS3 的 calc 函数 经典真题 CSS 的计算属性知道吗? CSS3 中的 calc 函数 calc 是英文单词 calculate(计算)的缩写,是 CSS3 的一个新增的功能。 MDN 的解释为可以用在任何长度、数值、时间、角度、频率等处,语法如…...
echrts 全国地图、各省市地图json文件下载
DataV.GeoAtlas地理小工具系列...
如何使用1688.item_search_shop API获取阿里巴巴店铺商品信息
要使用1688的item_search_shop API获取阿里巴巴店铺的商品信息,你通常需要遵循以下步骤: 1. 注册并获取API密钥 首先,你需要在阿里巴巴开放平台(如1688开放平台)上注册一个开发者账号,并创建一个应用。创…...
PLC_博图系列☞基本指令“取反RLO”
PLC_博图系列☞基本指令“取反RLO” 文章目录 PLC_博图系列☞基本指令“取反RLO”背景介绍取反RLO说明示例 关键字: PLC、 西门子、 博图、 Siemens 、 取反RLO 背景介绍 这是一篇关于PLC编程的文章,特别是关于西门子的博图软件。我并不是专业的PLC…...
docker安装PostGIS扩展
去docker仓库查找你想要安装的镜像版本,并pull下来 我下载的版本: [rootlocalhost ~]# docker pull postgis/postgis:12-3.2运行容器 [rootlocalhost ~]# docker run --name postgis --privilegedtrue --restartalways -e POSTGRES_USER12345678 -e P…...
LabVIEW开发FPGA的高速并行视觉检测系统
LabVIEW开发FPGA的高速并行视觉检测系统 随着智能制造的发展,视觉检测在生产线中扮演着越来越重要的角色,尤其是在质量控制方面。传统的基于PLC的视觉检测系统受限于处理速度和准确性,难以满足当前生产需求的高速和高精度要求。为此…...
P5734 【深基6.例6】文字处理软件 - Java
题目描述 你需要开发一款文字处理软件。最开始时输入一个字符串作为初始文档。可以认为文档开头是第 00 个字符。需要支持以下操作: 1 str:后接插入,在文档后面插入字符串 strstr,并输出文档的字符串;2 a bÿ…...
关于设备连接有人云的使用及modbus rtu协议,服务器端TCP调试设置
有人云调试 调试过程问题1. 关于modbus rtu协议,实质上有三种modbus基本原理modbus 格式2. 关于modbus crc16通信校验3. 关于在ubuntu阿里云服务器端,监听网络数据之调试mNetAssist4. 使用有人FAE传给的设置软件问题???之前的一个项目,再拿出来回顾下。 调试过程 先 要在有…...
开源图表库Echarts 简介与基本使用
ECharts 是一个使用 JavaScript 实现的开源可视化图表库,由百度团队开发。它提供了丰富的图表类型,如折线图、柱状图、饼图、地图、雷达图等,并且可以轻松地与其他前端框架和库集成。ECharts 的设计目的是为了满足复杂数据的可视化需求&#…...
变更ip后怎么查现在的代理ip地址?代理IP在网络请求中有哪些优势?
要查看当前的代理IP地址,可以尝试以下方法 浏览器设置:在大部分浏览器中,可以通过菜单选项中的“设置”或“帮助”来查找关于代理服务器的设置。在这里,可以看到当前使用的代理服务器地址、端口号以及是否启用了代理服务。在线工具…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
