07 MyBatis之高级映射 + 懒加载(延迟加载)+缓存

1. 高级映射

例如有两张表, 分别为班级表和学生表
自然, 一个班级对应多个学生

像这种数据 , 应该如果如何映射到Java的实体类上呢? 这就是高级映射解决的问题

以班级和学生为例子 , 因为一个班级对应多个学生 , 因此学生表中必定有一个班级编号字段cid

但我们在学生的实体类中不需要加入这个字段, 而是通过另一个方法实现一对多映射/多对一映射

1.1 高级映射的分类

  1. 关联映射(Association Mapping)
    关联映射用于处理对象之间的一对一关系。例如,一个订单对象可能包含一个关联的客户对象。通过使用 MyBatis 的关联映射,你可以在查询订单的同时,自动填充每个订单所关联的客户信息。

  2. 集合映射(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 二级缓存失效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/700118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Yolov9全文翻译!

Yolo v9全文翻译 论文链接&#xff1a;&#x1f47f; YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information 代码链接&#xff1a;&#x1f47f; https://github.com/WongKinYiu/yolov9/tree/main 大量图片来袭&#xff01;

为什么说抖店适合电商新手入局?门槛及运营玩法,今天一文详解!

大家好&#xff0c;我是电商小布。 现在&#xff0c;越来越多的人开始加入到了电商这个行业&#xff0c;原因就是看到了它发展的可能性。 而抖音小店这个项目&#xff0c;作为近几年发展势头非常猛的电商项目&#xff0c;成为了很多小伙伴们的首选。 为什么会这样呢&#xf…

抖音数据抓取工具|视频内容提取软件

引言部分&#xff1a; 介绍针对抖音视频下载需求开发的强大工具突出解决用户获取抖音视频繁琐问题的初衷 工具功能介绍&#xff1a; 详细描述工具功能&#xff0c;包括关键词搜索、自动批量抓取、选择性批量下载等提及基于C#开发的优势以及支持通过分享链接进行单个视频抓取…

10:部署Dashboard|部署Prometheus|HPA集群

部署Dashboard&#xff5c;部署Prometheus&#xff5c;HPA集群 Dashboard部署Dashboard上传镜像到私有仓库安装服务发布服务创建管理用户查看登录的Token信息 Prometheus步骤一&#xff1a;导入所有后续需要的镜像到私有镜像仓库&#xff08;在master主机操作操作&#xff09;步…

【区块链】智能交易模式下的数据安全流通模型

【区块链】智能交易模式下的数据安全流通模型 写在最前面**区块链智能交易模式概述****数据安全流通的挑战****数据安全流通模型的核心要素****实现数据安全流通的区块链技术****区块链智能交易模式下数据安全流通模型的设计原则****数据安全流通模型的应用案例分析****面临的挑…

ONLYOFFICE8.0——赋能办公

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-xdAoM2pHRmDFP0tF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

IDEA 重装我都会默默的下载这些好用的插件

本文已经收录公众号&#xff1a;面汤放盐 IDEA 重装我都会默默的下载这些好用的插件 (qq.com) 这几年用得最多的插件&#xff0c;分享给大家。工欲善其事&#xff0c;必先利其器&#xff01;每一次电脑重装&#xff0c;更换工作&#xff0c;我都会默默地打开我的插件收藏单&a…

SpringBoot项目实现文件上传,MINIO+OSS阿里云

MINIO 安装以及部署 官网&#xff1a;MinIO | Code and downloads to create high performance object storage 下载后是一个minio.exe的文件&#xff0c;可以先创一个文件夹来存放数据以及文件 在文件的目录下cmd进入控制台 minio.exe server data 启动成功后控制台会打印账…

Raspbian命令行RTSP/RTP服务

Raspbian命令行RTSP/RTP服务 1. 源由2. Raspbian摄像头2.1 命令行启动RTP摄像头2.2 命令行启动RTSP摄像头 3. 示例3.1 测试RTP摄像头3.2 测试RTSP摄像头3.3 QGroundControl测试3.3.1 RTSP配置3.3.2 RTP配置 4. 总结5. 参考资料 1. 源由 鉴于实际测试发现RTP协议下&#xff0c;…

利用DevOps和ITSM的集成能促进IT技术

在当今这个快节奏和技术驱动的世界里&#xff0c;DevOps 和 IT 服务管理&#xff08;ITSM&#xff09;理念在培养心理健康和减少技术压力的工作环境中正在发挥重要作用。混合最佳实践&#xff0c;实现更好、更快、更安全的服务。 什么是DevOps&#xff1f; DevOps 专注于采用协…

多人协作记账账本小程序开源版开发

多人协作记账账本小程序开源版开发 支持多人协作的记账本小程序&#xff0c;可用于家庭&#xff0c;团队&#xff0c;组织以及个人的日常收支情况记录&#xff0c;支持周月年度统计 便捷记账 便捷的记账方式&#xff0c;支持多种记账类型&#xff0c;快捷切换账本等 多账本 支…

猫头虎分享已解决Bug || ValueError: Setting an array element with a sequence.

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

python 基础知识点(蓝桥杯python科目个人复习计划49)

今日复习内容&#xff1a;做复习题 例题1&#xff1a;希尔排序 题目描述&#xff1a; 希尔排序是直接插入排序算法的一种更高效的改进版本&#xff0c;但它是非稳定排序算法。希尔排序是基于插入排序的以下两点性质而提出的改进方法之一&#xff1a; 1.插入排序在对几乎已经…

C++初阶:容器适配器priority_queue常用接口详解及模拟实现、仿函数介绍

介绍完了stack和queue的介绍以及模拟的相关内容后&#xff1a;C初阶&#xff1a;容器适配器介绍、stack和queue常用接口详解及模拟实现 接下来进行priority_queue的介绍以及模拟&#xff1a; 文章目录 1.priority_queue的介绍和使用1.1priority_queue的初步介绍1.2priority_que…

Spring 手动实现Spring底层机制

目录 一、前言 二、Spring底层整体架构 1.准备工作 : 2.架构分析 : &#xff08;重要&#xff09; 3.环境搭建 &#xff1a; 三、手动实现Spring容器结构 1.自定义注解 : 1.1 Component注解 1.2 Scope注解 2.自定义组件 : 3.自定义用于封装Bean信息的BeanDefinition类&a…

【MySQL系列 04】深入浅出索引

一、索引介绍 提到数据库索引&#xff0c;相信大家都不陌生&#xff0c;在日常工作中会经常接触到。比如某一个 SQL 查询比较慢&#xff0c;分析完原因之后&#xff0c;你可能就会说“给某个字段加个索引吧”之类的解决方案。 但到底什么是索引&#xff0c;索引又是如何工作的…

【多线程】volatile 关键字、wait 和 notify方法详解

volatile 、wait 和 notify &#x1f332;volatile关键字&#x1f6a9;保证内存可见性&#x1f6a9;volatile 不保证原⼦性 &#x1f333;wait 和 notify方法&#x1f6a9;wait()&#x1f6a9;notify()&#x1f6a9;notifyAll()方法 ⭕wait 和 sleep 的对比&#xff08; 面试题…

基础光学系列:(一)光学在机器视觉中的角色:原理、应用与学习途径

光学是一门研究光的产生、传播以及与物质相互作用的科学&#xff0c;对于机器视觉技术的发展至关重要。机器视觉利用计算机和相机系统模拟人类视觉&#xff0c;解释和理解图像&#xff0c;广泛应用于制造业、医疗、安全监控等领域。本文旨在探讨光的传播原理及其在机器视觉中的…

低于API等级30的应用将无法在上述应用商店

minSdkVersion minSdkVersion用于指定应用兼容的最低Android版本&#xff08;API等级&#xff09;。 如果APP某些功能无法支持低版本Android系统的设备&#xff0c;可以配置minSdkVersion确保APP只能安装到指定Android版本以上的设备。HBuilder|HBuilderX中可在manifest.json中…

Linux快速修改ip地址

Linux修改IP配置 一 、查找ip配置文件 ifcfg-ens33二、编辑 vi ifcfg-ens33文件三、重启网络或者重启系统 一 、查找ip配置文件 ifcfg-ens33 cd /etc/sysconfig/network-scripts/ls //查看network-scripts文件夹下面的文件二、编辑 vi ifcfg-ens33文件 vi ifcfg-ens33注意&…