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地址,可以尝试以下方法 浏览器设置:在大部分浏览器中,可以通过菜单选项中的“设置”或“帮助”来查找关于代理服务器的设置。在这里,可以看到当前使用的代理服务器地址、端口号以及是否启用了代理服务。在线工具…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...