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

MyBatis系统学习(四)——MyBatis的关联映射和缓存机制

MyBatis 是一个优秀的持久层框架,它通过 XML 或注解将 Java 对象与 SQL 语句相映射,简化了 JDBC 代码,增强了 SQL 的灵活性。在复杂业务场景中,数据库表之间经常存在一对一、一对多、多对多的关联关系,MyBatis 提供了相应的机制来处理这些映射问题。此外,MyBatis 的缓存机制可以有效提高数据访问效率。

接下来,我将详细介绍 MyBatis 中的关联映射和缓存机制。

一、MyBatis 关联映射概述

在关系型数据库中,表与表之间的关联关系常见的有:

  • 一对一(One-to-One):两个表中一条记录对应另一个表中的一条记录。
  • 一对多(One-to-Many):一个表中一条记录对应另一个表中的多条记录。
  • 多对多(Many-to-Many):两个表中的多条记录彼此关联。

MyBatis 提供了以下两种主要方式来实现关联映射:

  1. 使用 resultMap 标签进行复杂的对象关系映射
  2. 通过注解来实现简单的映射

二、一对一查询

一对一关系通常体现在数据库中表与表之间通过外键关联。MyBatis 支持通过 resultMap 标签来定义一对一的关联关系。

实现步骤:

  1. 在数据库中,两个表具有外键关联。例如,User 表和 Address 表,User 表有一个 address_id 外键指向 Address 表。
  2. 在 MyBatis 的配置文件中,通过 resultMap 定义关联关系。
示例:

假设我们有 UserAddress 表,User 表中有一个 address_id 作为外键关联 Address 表。

<!-- 一对一映射 resultMap -->
<resultMap id="userResultMap" type="com.example.User"><id property="id" column="id"/><result property="name" column="name"/><association property="address" javaType="com.example.Address"><id property="id" column="address_id"/><result property="city" column="city"/><result property="street" column="street"/></association>
</resultMap><select id="selectUserWithAddress" resultMap="userResultMap">SELECT u.id, u.name, a.id AS address_id, a.city, a.streetFROM User uLEFT JOIN Address a ON u.address_id = a.idWHERE u.id = #{id}
</select>

这里,<association> 用于描述一对一的关系。User 对象的 address 属性将与 Address 对象对应。

三、一对多查询

一对多关系通常表示一个表中的一条记录可以对应另一个表中的多条记录。MyBatis 可以通过 collection 标签来处理一对多的关系。

示例:

假设 User 表和 Order 表存在一对多的关系,一个用户可以有多个订单。

<!-- 一对多映射 resultMap -->
<resultMap id="userWithOrdersResultMap" type="com.example.User"><id property="id" column="id"/><result property="name" column="name"/><collection property="orders" ofType="com.example.Order"><id property="id" column="order_id"/><result property="orderNumber" column="order_number"/><result property="amount" column="amount"/></collection>
</resultMap><select id="selectUserWithOrders" resultMap="userWithOrdersResultMap">SELECT u.id, u.name, o.id AS order_id, o.order_number, o.amountFROM User uLEFT JOIN Orders o ON u.id = o.user_idWHERE u.id = #{id}
</select>

这里使用 <collection> 标签定义了 User 对象中包含的 orders 集合。通过这个映射,MyBatis 会自动将查询到的 Order 记录映射到 User 对象的 orders 属性中。

四、多对多查询

多对多的关系通常通过中间表来表示,MyBatis 也可以处理这样的复杂关联。

示例:

假设 Student 表和 Course 表通过 Student_Course 中间表存在多对多关系。

<!-- 多对多映射 resultMap -->
<resultMap id="studentWithCoursesResultMap" type="com.example.Student"><id property="id" column="id"/><result property="name" column="name"/><collection property="courses" ofType="com.example.Course"><id property="id" column="course_id"/><result property="courseName" column="course_name"/></collection>
</resultMap><select id="selectStudentWithCourses" resultMap="studentWithCoursesResultMap">SELECT s.id, s.name, c.id AS course_id, c.course_nameFROM Student sLEFT JOIN Student_Course sc ON s.id = sc.student_idLEFT JOIN Course c ON sc.course_id = c.idWHERE s.id = #{id}
</select>

这里使用 <collection> 定义了 Student 对象中包含的 courses 集合。查询结果会自动映射到 Student 对象的 courses 属性中。

五、MyBatis 缓存机制

MyBatis 提供了两级缓存机制:

  1. 一级缓存(Local Cache):基于 SqlSession 的缓存。一级缓存默认开启,且作用范围是 SqlSession 级别的。在同一个 SqlSession 中执行相同的 SQL 语句,MyBatis 会从缓存中取数据而不是再去查询数据库。
  2. 二级缓存(Global Cache):基于 mapper 映射文件的缓存。作用范围是 mapper 映射文件级别,即同一个 mapper 中的多个 SqlSession 都可以共享该缓存。二级缓存需要手动配置开启。
一级缓存:
  • 默认情况下一级缓存是开启的。
  • 一级缓存的生效条件:同一个 SqlSession、相同的查询条件。
示例:
SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUser", 1); // 从数据库查询
User user2 = session.selectOne("selectUser", 1); // 从缓存中查询
二级缓存:

二级缓存需要在 mapper 映射文件中手动开启,且 Java 类必须实现序列化接口。

配置方式:
  1. 在 MyBatis 配置文件中开启二级缓存:

    <settings><setting name="cacheEnabled" value="true"/>
    </settings>
    
  2. mapper 文件中开启二级缓存:

    <cache/>
    
  3. Java 对象必须实现 Serializable 接口,确保对象能被序列化并存入缓存。

二级缓存失效的条件:
  • 执行了增删改操作,相关缓存会失效。
  • 不同的 SqlSession

六、MyBatis 相关常用知识点总结

  1. 动态 SQL:MyBatis 提供了 ifchoosewhenforeach 等标签来处理动态 SQL,满足多变的业务需求。
  2. resultMap 的使用resultMap 是 MyBatis 最强大的功能之一,它允许灵活地将查询结果映射到复杂的 Java 对象中。
  3. 多数据源支持:MyBatis 支持多数据源的配置,可以方便地在项目中切换或同时操作多个数据库。
  4. 分页插件:MyBatis 本身不提供分页功能,但是可以通过插件(如 PageHelper)来实现数据库层面的分页操作。

七、综合案例

假设我们有三个表:User 表、Order 表和 Product 表。User 表与 Order 表是一对多的关系,Order 表与 Product 表是多对多的关系(通过 Order_Product 中间表实现)。我们希望查询用户、用户的订单以及每个订单中的产品信息。

数据库表设计:
  • User 表:idname
  • Order 表:idorder_numberuser_id
  • Product 表:idproduct_name
  • Order_Product 表:order_idproduct_id
MyBatis 配置文件:
<!-- 综合案例 resultMap -->
<resultMap id="userWithOrdersAndProductsResultMap" type="com.example.User"><id property="id" column="id"/><result property="name" column="name"/><collection property="orders" ofType="com.example.Order"><id property="id" column="order_id"/><result property="orderNumber" column="order_number"/><collection property="products" ofType="com.example.Product"><id property="id" column="product_id"/><result property="productName" column="product_name"/></collection></collection>
</resultMap><select id="selectUserWithOrdersAndProducts" resultMap="userWithOrdersAndProductsResultMap">SELECT u.id, u.name, o.id AS order_id, o.order_number, p.id AS product_id, p.product_nameFROM User uLEFT JOIN Orders o ON u.id = o.user_idLEFT JOIN Order_Product op ON o.id = op.order_idLEFT JOIN Product p ON op.product_id = p.idWHERE u.id = #{id}
</select>
Java 类设计:
public class User implements Serializable {private Integer id;private String name;private List<Order> orders;// getters and setters
}public class Order implements Serializable {private Integer id;private String orderNumber;private List<Product> products;// getters and setters
}public class Product implements Serializable {private Integer id;private String productName;// getters and setters
}

通过以上配置和映射,当执行 selectUserWithOrdersAndProducts 查询时,MyBatis 会将用户、订单和订单中的产品信息自动映射到 User 对象及其关联的 OrderProduct 对象中。

结语

MyBatis 在处理复杂的对象关系映射时提供了极大的灵活性。通过 resultMap 和缓存机制,我们能够有效地管理查询结果并提升系统性能。在实际开发中,掌握 MyBatis 的这些功能,可以更轻松地应对持久层的复杂逻辑。

相关文章:

MyBatis系统学习(四)——MyBatis的关联映射和缓存机制

MyBatis 是一个优秀的持久层框架&#xff0c;它通过 XML 或注解将 Java 对象与 SQL 语句相映射&#xff0c;简化了 JDBC 代码&#xff0c;增强了 SQL 的灵活性。在复杂业务场景中&#xff0c;数据库表之间经常存在一对一、一对多、多对多的关联关系&#xff0c;MyBatis 提供了相…...

【iOS】present和push

【iOS】present和push present和push的比较 present和push都用于iOS的视图切换&#xff0c;并且切换都是可逆的&#xff0c;原始视图不会被销毁&#xff0c;还可以直接更改window的rootViewController来切换视图&#xff0c;但是这种方法不可逆&#xff0c;并且原始视图会被销毁…...

Axure RP 9最新安装程序及汉化包下载(支持Win、Mac版,附下载安装教程)

数月前Axure RP官方已经发布了Axure RP 9的消息&#xff0c;并计划在今年夏天发布beta版本。新版Axure RP 9将是该工具向前迈出的重要一步&#xff0c;其中包括一系列广泛的改进&#xff1a;全面的UI修改&#xff0c;新的设计和文档功能以及前所未有的内部优化。我们已经彻底重…...

k8s环境搭建(续)

查看节点信息并做快照 kubectl get nodes 将components.yml文件上传到master主机 创建nginx&#xff0c;会在添加一个新的pod kubectl run nginx --imagesnginx:latest 查看nginx的pod信息 [rootk8s-master ~]# kubectl get po -Aowide|grep nginx 出现错误&#xff0c;查…...

kali——binwalk的使用

目录 前言 使用方法 分析文件 分离文件 前言 binwalk是一个用于分析、逆向工程和提取固件映像的工具。 binwalk能够分析固件映像文件&#xff0c;识别其中包含的文件。例如&#xff0c;它可以从一个设备固件中提取出压缩文件或图片等嵌入内容。 使用方法 分析文件 binwa…...

Ubuntu 24.04中安装virtualenv

在Ubuntu 24.04中安装virtualenv&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确保Python已安装‌&#xff1a; 在终端中输入python --version或python3 --version来检查Python的安装情况。 python3 --version2. 安装pip‌&#xff08;如果尚未安装&#xff09;&#x…...

一个简约的uniapp登录界面,基于uniapp+vue3+uview-plus

uniapp-vue3-template 一个简约的uniapp登录界面&#xff0c;基于uniappvue3uview-plus 页面主要包括&#xff1a;用户登录&#xff0c;手机验证码登录&#xff0c;用户注册&#xff0c;重置密码等页面 登录进去后为空白模板 源码在文末 界面 源码 uniapp登录界面源码...

系统架构设计师 需求分析篇二

&#x1f4d8; 面向对象分析方法 1. 用例模型 &#x1f4c8; 构建用例模型一般需要经历 4 个阶段&#xff1a; 识别参与者 &#x1f50d;&#xff1a;识别与系统交互的所有事物。合并需求获得用例 &#x1f517;&#xff1a;将需求分配给予其相关的参与者。细化用例描述 &am…...

IP 协议分析《实验报告》

目录 一、 实验目的 二、实验设备和环境 三、实验记录 1、实验环境搭建 2、IP 协议分析 1.设置抓包接口 2.IP 报文分析 3.报文长度计算 4.生存时间 TTL 5.分析总结 3、IP分片 1.IP 分片简介 2.捕获分组 3.结果分析 一、 实验目的 1、掌握 IP 协议数据报格式&…...

人工智能开发实战matplotlib库应用基础

内容导读 matplotlib简介绘制直方图绘制撒点图 一、matplotlib简介 matplotlib是一个Python 2D绘图库&#xff0c;它以多种硬拷贝格式和跨平台的交互式环境生成高质量的图形。 matplotlib 尝试使容易的事情变得更容易&#xff0c;使困难的事情变得可能。 我们只需几行代码…...

Android 源码集成可卸载 APP

android系统包含三类APP: 1、可自由卸载APP安装在 /data/app目录下。 2、系统APP放在 /system/app目录。 3、特权APP放在 /system/priv-app目录。 系统编译后&#xff0c;打包前&#xff0c; /data分区不起作用&#xff0c;因此系统打包前&#xff0c;可以先将APP全部拷贝到 /…...

cJSON-轻量级解析模块、字符串的神——编织STM32C8T6与阿里云信息传递的纽带

编写方向&#xff1a;本人就不泛泛的编写一篇什么一文学会cJSON了&#xff0c;没什么突出点&#xff0c;也就我水水字数&#xff0c;你们看来看去也不懂&#xff0c;本人是从上阿里云传信息接触的cJSON的&#xff0c;我就此写一篇针对性的文章&#xff0c;希望对大家有用&#…...

【Git】Clone

当git clone失败时&#xff0c;出现 RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8) 错误&#xff0c;可能由于网络连接不稳定或仓库太大导致的。 可以尝试以下几种方法来解决这个问题&#xff1a; 增加 Git 的缓冲区大小&#xff1a; git confi…...

web开发 之 HTML、CSS、JavaScript、以及JavaScript的高级框架Vue(学习版2)

一、前言 接下来就是来解决这些问题 二、 Ajax 1.ajax javscript是网页三剑客之一&#xff0c;空用来控制网页的行为的 xml是一种标记语言&#xff0c;是用来存储数据的 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-…...

【课程学习】信号检测与估计II

b站 文章目录 1-概述 1-概述 线性、正交、平稳、高斯 研究线性模型&#xff0c;采用正交化方法&#xff0c;假设信号平稳&#xff0c;考虑信号的统计特性是高斯的。 本学期考虑&#xff0c;非线性、非正交、非平稳、非高斯。 阵列处理 1980-1990 MUSIC 稀疏性 2006-2012 LASS 时…...

【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释!

【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释&#xff01; 【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释&#xff01; 论文地址&#xff1a; https://arxiv.org/abs/1505.04597 代码地址&a…...

DPDK基础入门(十):虚拟化

I/O虚拟化 全虚拟化&#xff1a;宿主机截获客户机对I/O设备的访问请求&#xff0c;然后通过软件模拟真实的硬件。这种方式对客户机而言非常透明&#xff0c;无需考虑底层硬件的情况&#xff0c;不需要修改操作系统。 半虚拟化&#xff1a;通过前端驱动/后端驱动模拟实现I/O虚拟…...

OpenCV_图像旋转超详细讲解

图像转置 transpose(src, dst); transpose()可以实现像素下标的x和y轴坐标进行对调&#xff1a;dst(i,j)src(j,i)&#xff0c;接口形式 transpose(InputArray src, // 输入图像OutputArray dst, // 输出 ) 图像翻转 flip(src, dst, 1); flip()函数可以实现对图像的水平翻转…...

关于 OceanBase 4.x 中被truncate的 table 不再支持进回收站的原因

近期&#xff0c;OceanBase的问答社区中收到了不少用户的询问&#xff0c;关于OceanBase 3.x版本支持被truncate的table进入回收站的功能&#xff0c;为何在升级到4.x版本后不再支持了&#xff1f;为了解答大家的疑惑&#xff0c;我们将通过这篇文章来浅析 OceanBase在4.x版本中…...

Numpy索引详解(数值索引,列表索引,布尔索引)

数值索引 数值索引类似列表索引操作使用[]&#xff0c;参数为下标&#xff0c;[0,len-1),高维数组的索引使用多个[]连用分别代表一维索引&#xff0c;二维索引... import numpy as np import torchnp.random.seed(1) data1 np.arange(5) data2 np.arange(15).reshape(3,5) …...

企业语音 AI 困境待解:用户体验成破局关键

【导语&#xff1a;语音 AI 智能助手市场规模预计大幅增长&#xff0c;但企业应用成熟度低。当前企业语音 AI 面临诸多困境&#xff0c;需从用户体验出发解决问题&#xff0c;本文探讨了相关原则、研究方法及对自主语音 AI 的影响。】语音 AI 市场增长与企业应用困境语音 AI 智…...

SoftSerial软件串口原理与STM32工程实践

1. SoftSerial 库深度解析&#xff1a;面向资源受限 MCU 的软件 UART 实现原理与工程实践1.1 背景与工程必要性在嵌入式系统开发中&#xff0c;UART&#xff08;通用异步收发传输器&#xff09;是最基础、最广泛使用的串行通信接口。然而&#xff0c;MCU 的硬件 UART 资源往往极…...

Ansible Playbook实战指南:从基础到高级技巧全解析

1. Ansible Playbook基础入门 第一次接触Ansible Playbook时&#xff0c;我被它简洁的YAML语法和强大的自动化能力惊艳到了。记得当时需要给50台服务器部署Nginx&#xff0c;传统方式要手动操作每台机器&#xff0c;而用Playbook只花了10分钟就搞定了全部部署。这种效率提升让我…...

卡尔曼滤波:详细齐全的代码实现与解析

卡尔曼滤波&#xff08;代码非常详细、非常齐全&#xff09; 1、卡尔曼滤波的含义是现时刻的最佳估计为在前一时刻的最佳估计的基础上根据现时刻的观测值作线性修正 2、卡尔曼滤波在数学上是一种线性最小方差统计估算方法&#xff0c;它是通过处理一系列带有误差的实际测量数据…...

谐波注入抑制永磁同步电机转矩脉动的复现研究

提取特定谐波注入抑制永磁同步电机转矩脉动【复现】 [1]复现文献&#xff1a;《用谐波注入抑制永磁同步电机转矩脉动_廖勇》 [2]控制思路&#xff1a;以抑制电机电流中较大的 5、7 次谐波分量为目的&#xff0c;实时提取谐波电流&#xff0c;注入谐波电压来抵消电机运行时电机电…...

YOLO26涨点改进| TPAMI 2026 |独家创新首发、Conv改进篇| 引入LPM 局部先验特征增强模块,更加聚焦于目标区域并抑制背景干扰,助力目标检测、图像分割、图像恢复、图像增强有效涨点

一、本文介绍 🔥本文给大家介绍使用 LPM 局部先验特征增强模块 改进YOLO26网络模型,通过构建重要性图对特征提取过程进行引导,使模型能够更加聚焦于目标区域并抑制背景干扰,从而提升特征表达质量和目标区分能力。其优势体现在能够有效增强关键区域信息、提升小目标和复杂…...

紧固件模具是什么?生产工艺、类型及应用详解_FES上海紧固件展

2026第十六届上海紧固件专业展Fastener Expo Shanghai 2026将于6月24日至26日在国家会展中心&#xff08;上海&#xff09;举行。展会由上海上搜展览与华人螺丝网联合主办&#xff0c;并获得中国五矿化工进出口商会五金紧固件分会支持&#xff0c;整体展览规模约70,000平方米&a…...

ChatGPT上车CarPlay:智能交互新突破与安全边界的平衡

ChatGPT集成CarPlay&#xff1a;行车途中的语音智能交互4月3日&#xff0c;OpenAI宣布ChatGPT正式获得苹果CarPlay系统的集成支持。这一更新让CarPlay用户能够在车载仪表盘界面直接通过语音与ChatGPT进行交互&#xff0c;实现了行车途中的免提提问与请求服务。该功能的实现得益…...

Qt图形界面开发:Phi-3-mini生成UI代码片段与信号槽连接示例

Qt图形界面开发&#xff1a;Phi-3-mini生成UI代码片段与信号槽连接示例 1. 引言&#xff1a;当AI遇上Qt界面开发 作为一名Qt开发者&#xff0c;你是否经常陷入这样的困境&#xff1a;每次新建一个对话框或窗口&#xff0c;都要重复编写相似的UI初始化代码&#xff1f;特别是当…...

KeyboardChatterBlocker:如何解决机械键盘的“幽灵按键“问题?

KeyboardChatterBlocker&#xff1a;如何解决机械键盘的"幽灵按键"问题&#xff1f; 【免费下载链接】KeyboardChatterBlocker A handy quick tool for blocking mechanical keyboard chatter. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyboardChatterBlocke…...