mybatis学习:四、关联查询、缓存

news2025/1/9 12:32:49

7. 关联查询

7.1 准备工作:

数据库表:

#订单表:
create table tb_order
(
  id         INT  AUTO_INCREMENT  PRIMARY KEY,
  userid     INT,
  createtime DATETIME,
  state      VARCHAR(20)
) ENGINE=InnoDB AUTO_INCREMENT=1;

#订单详情表
CREATE TABLE  tb_orderdetail(
  id INT  AUTO_INCREMENT  PRIMARY KEY,
  productId  INT,
  ordereId  INT,
  num INT,
  price DOUBLE(8,2)
) ENGINE=InnoDB AUTO_INCREMENT=1;

#商品表
CREATE TABLE  tb_product (
   id  INT  AUTO_INCREMENT  PRIMARY KEY,
  name  varchar(100),
  price  DOUBLE(8,2),
  description  varchar(500)
) ENGINE=InnoDB AUTO_INCREMENT=1 ;

#用户表
CREATE TABLE tb_user(
  ID INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(20),
  PASSWORD VARCHAR(50),
  sex VARCHAR(2),
  brithday DATE,
  address VARCHAR(200)
) ENGINE=INNODB AUTO_INCREMENT=1 ;

表与表之间的关联:
在这里插入图片描述

7.2 一对一查询

需求:

查询订单信息,以及关联的用户信息

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

实体类:

在这里插入图片描述

Sql映射文件:

使用resultMap定义输出参数,

<!-- 定义一个包含用户信息的Order的ResultMap -->
	<resultMap type="Order" id="orderMap">
		<id column="id" property="id"/>
		<result column="createTime" property="createTime"/>
		<result column="state" property="state"/>
		<!-- 配置关联属性User的信息  -->
		<!-- association:用于映射关联单个对象信息 
			property:关联的属性名,就是将用户对象关联到Order的那个属性
			javaType: 属性的类型
		-->
		<association property="user" javaType="User">
			<id column="id" property="id"></id>
			<result column="username" property="name"/>
			<result column="sex" property="sex"/>
			<result column="password" property="password"/>
			<result column="address" property="address"/>
			<result column="brithday" property="brithday"/>
		</association>
	</resultMap>

SQL语句

<!-- 查询订单以及该订单所关联的用户 -->
<select id="findOrders" resultMap="orderMap">
    SELECT o.* , u.username,u.address FROM tb_order o , tb_user u WHERE o.userId = u.id
</select>

Mapper接口:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCWkGG3n-1669619415257)(assets/wps10.jpg)]

测试代码:
在这里插入图片描述

7.3 一对多查询

需求:

查询用户,及用户下的所有订单信息

User类:

​ 需要在User类添加一个订单的关联属性,但是一个用户是可以有多个订单的,所以该属性是一个集合属性.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XqgneDYN-1669619415265)(assets/wps12.jpg)]

定义一个包含Order信息的User的ResultMap:

<!-- 定义一个包含Order信息的User的ResultMap -->
	<resultMap type="User" id="userOrderMap">
		<id column="id" property="id"></id>
			<result column="username" property="name"/>
			<result column="sex" property="sex"/>
			<result column="password" property="password"/>
			<result column="address" property="address"/>
			<result column="brithday" property="brithday"/>
		<!-- 订单信息 -->
		<!-- 
			collection:对关联查询到的多条记录映射到集合对象中
			property:将查询到的多条记录映射到User类的那个属性中
			ofType: 指明集合中的元素的类型
		 -->
		<collection property="orders" ofType="Order">
			<id column="oid" property="id"></id>
			<result column="createTime" property="createTime"/>
			<result column="state" property="state"/>
		</collection>
	</resultMap>

SQL语句定义:

<!-- 查询用户以及该用户的订单信息 -->
	<select id="findUserOrder" resultMap="userOrderMap">
		select u.* ,o.id oid,o.createtime,o.state  from tb_user u , tb_order o where u.id = o.userId
	</select>

级联查询的时候,主表和从表有一样的字段名的时候,在mysql上命令查询是没问题的。但在mybatis中主从表需要为相同字段名设置别名

Mapper 接口:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHWKp1hh-1669619415269)(assets/wps13.jpg)]

测试代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwXpseUd-1669619415270)(assets/wps14.jpg)]

7.4 多对多查询

需求:

查询用户,及用户的订单信息和订单详情信息

SQL语句:

查询主表是:用户表

关联表:由于用户和订单详情表没有直接关联,通过订单进行关联

SELECT  u.*, o.id oid , o.createTime, o.state, d.id orderdetailId, d.price,d.num
 FROM tb_user u, tb_order o, tb_orderdetail d
WHERE u.id = o.userId  AND  o.id =d.orderId

映射思路:

将用户信息映射到user中。

在user类中添加订单列表属性List orders,将用户创建的订单映射到orders

在Orders中添加订单明细列表属性Listorderdetials,将订单的明细映射到orderdetials
在这里插入图片描述

resultMap:

<!-- 定义一个包含Order信息以及OrderDetail信息的User的ResultMap -->
	<resultMap type="User" id="userOrderOrderDetailMap">
		<id column="id" property="id"></id>
			<result column="username" property="name"/>
			<result column="sex" property="sex"/>
			<result column="password" property="password"/>
			<result column="address" property="address"/>
			<result column="brithday" property="brithday"/>
		<!-- 订单信息 -->
		<!-- 
			collection:对关联查询到的多条记录映射到集合对象中
			property:将查询到的多条记录映射到User类的那个属性中
			ofType: 指明集合中的元素的类型
		 -->
		<collection property="orders" ofType="Order">
			<id column="oid" property="id"></id>
			<result column="createTime" property="createTime"/>
			<result column="state" property="state"/>
			<!-- 订单详情信息 -->
			<collection property="orderDetails" ofType="OrderDetail">
				<id column="orderDetailId" property="id"></id>
				<result column="price" property="price"/>
				<result column="num" property="num"/>
			</collection>
		</collection>
	</resultMap>

SQL映射:

<!-- 查询用户以及该用户的订单及订单详情 -->
	<select id="findUserOrderOrderDetail" resultMap="userOrderOrderDetailMap">
		SELECT  u.*, o.id oid , o.createTime, o.state, d.id orderdetailId, d.price,d.num
 		FROM tb_user u, tb_order o, tb_orderdetail d
		WHERE u.id = o.userId  AND  o.id =d.orderId
	</select>

Mapper接口:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RRXyBHLv-1669619415277)(assets/wps19.jpg)]

测试代码:
在这里插入图片描述

8. 缓存

8.1 MyBatis的缓存简介

如下图,是mybatis一级缓存和二级缓存的区别图解:
在这里插入图片描述

​ Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。

​ Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。

8.2 一级缓存

下图是根据id查询用户的一级缓存图解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vyT0whu-1669619415290)(assets/wps22.png)]

​ 一级缓存区域是根据SqlSession为单位划分的。

​ 每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。

​ Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象,sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

测试:

@Test
public void testCache1() throws Exception{
    SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //下边查询使用一个SqlSession
    //第一次发起请求,查询id为1的用户
    User user1 = userMapper.findUserById(1);
    System.out.println(user1);

    //如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

    //更新user1的信息
    user1.setUsername("习大大");
    userMapper.updateUser(user1);
    //执行commit操作去清空缓存
    sqlSession.commit();

    //第二次发起请求,查询id为1的用户
    User user2 = userMapper.findUserById(1);
    System.out.println(user2);

    sqlSession.close();

}

分析:

​ 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

​ 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

​ 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

8.3 二级缓存

下图是多个sqlSession请求UserMapper的二级缓存图解。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjTSZ4sq-1669619415292)(assets/wps23.png)]

​ 二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper划分。

​ 每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。

​ Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

​ sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

开启二级缓存:

在核心配置文件mybatis-config.xml中加入

<setting name="cacheEnabled" value="true"/>
配置项描述允许值默认值
cacheEnabled对在此配置文件下的所有cache 进行全局性开/关设置。true falsetrue

要在你的Mapper映射文件中添加一行: <cache /> ,表示此mapper开启二级缓存。

实体类要实现序列化

​ 二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。

public class Order implements Serializable

public class User implements Serializable
...

测试

//获取session1
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper userMapper = session1.getMapper(UserMapper.class);
//使用session1执行第一次查询
User user1 = userMapper.findUserById(1);
System.out.println(user1);
//关闭session1
session1.close();
//获取session2
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
//使用session2执行第二次查询,由于开启了二级缓存这里从缓存中获取数据不再向数据库发出sql
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
//关闭session2
session2.close();

8.4 禁用二级缓存

​ 在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

is内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

​ sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

开启二级缓存:

在核心配置文件mybatis-config.xml中加入

<setting name="cacheEnabled" value="true"/>
配置项描述允许值默认值
cacheEnabled对在此配置文件下的所有cache 进行全局性开/关设置。true falsetrue

要在你的Mapper映射文件中添加一行: <cache /> ,表示此mapper开启二级缓存。

实体类要实现序列化

​ 二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。

public class Order implements Serializable

public class User implements Serializable
...

测试

//获取session1
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper userMapper = session1.getMapper(UserMapper.class);
//使用session1执行第一次查询
User user1 = userMapper.findUserById(1);
System.out.println(user1);
//关闭session1
session1.close();
//获取session2
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
//使用session2执行第二次查询,由于开启了二级缓存这里从缓存中获取数据不再向数据库发出sql
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
//关闭session2
session2.close();

8.4 禁用二级缓存

​ 在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

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

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

相关文章

[附源码]Python计算机毕业设计SSM酒店式公寓服务系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[LeetCode 1769]移动所有球到每个盒子所需的最小操作数

题目描述 题目链接&#xff1a;[LeetCode 1769]移动所有球到每个盒子所需的最小操作数 有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes &#xff0c;其中 boxes[i] 的值为 ‘0’ 表示第 i 个盒子是 空 的&#xff0c;而 boxes[i] 的值为 ‘1’ 表示盒子里有 一个 小球。…

Gradle简单配置

写在前面&#xff1a;一开始配置gradle的时候&#xff0c;最好不要把他maven仓库配置在一起&#xff0c;前段时间配置公司项目身心俱疲。大部分公司里面用gradle都是配置的自己的仓库地址&#xff0c;所以有的东西就不要和网上的配置保持一致了&#xff0c;比如说这个仓库地址。…

网站都变成灰色了,它是怎么实现的?

大家好&#xff0c;我是二哥呀。 想必大家都感受到了&#xff0c;很多网站、APP 在昨天都变灰了。 先来感受一下变灰后的效果。 这种灰色的效果怎么实现的呢&#xff1f;如何做到图片、文字、按钮都变灰的效果呢&#xff1f; 方案 1&#xff0c;换一套灰色的 UI&#xff0c;…

Github限时开源24小时,Alibaba架构师内部最新发布SpringCloud开发手册

前言 微服务是SOA之后越来越流行的体系结构模式之一&#xff01; 如果您关注行业趋势&#xff0c;就会发现,如今商业机构不再像几年前那样&#xff0c;开发大型应用程序&#xff0c;来管理端到端之间的业务功能&#xff0c;而是选择快速灵活的微服务。 ​ 通过微服务&#x…

Unity 之 后处理实现界面灰度效果(PostProcessing实现 | Shader实现)

Unity 之 后处理实现界面灰度效果前言一&#xff0c;Post Processing1.1 设置组件1.2 代码控制二&#xff0c;Shader材质实现2.1 原理API2.2 编写Shader2.3 编写代码2.4 实现效果效果展示前言 在Unity中实现后处理效果有两种方式&#xff1a;一种是通过使用Unity官方提供的Pos…

H3C AC三层组网架构,AP自动上线自动固化

核心交换机: [HX]dis cu [HX]dis current-configuration version 7.1.075, Alpha 7571 sysname HX irf mac-address persistent timer irf auto-update enable undo irf link-delay irf member 1 priority 1 dhcp enable lldp global enable system-working-mode standard xbar…

[附源码]计算机毕业设计仓库管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

C#连接MySql数据库

C#连接MySql数据库 具体步骤如下 第一步&#xff1a;提前将mysql服务打开&#xff0c;用xampp的需要将Mysql服务开启&#xff1b; 第二步&#xff1a;新建一个C#项目 第三步&#xff1a;在项目中下载&#xff1a;MySql.Data的NuGet&#xff0c;作者为Oracle&#xff1b; 第四布…

免息配资天宇优配|世界杯与A股有何关系?券商这样分析!

世界杯与A股有何联系&#xff1f; 卡塔尔世界杯开幕近两周&#xff0c;世界各地球迷热切关注。与此一起&#xff0c;不少金融机构“频频出镜”&#xff0c;多家券商发布了世界杯相关论题研究报告&#xff0c;讨论“世界杯效应”是否存在、世界杯期间是否利好大消费板块等论题。…

代码随想录刷题|LeetCode 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

目录 309.最佳买卖股票时机含冷冻期 思路 1、确定dp数组以及下标含义 2、确定递推公式 3、初始化 4、遍历顺序 5、获取结果 最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费 思路 买卖股票的最佳时机含手续费 309.最佳买卖股票时机含冷冻期 题目链接&#xff1a;力扣…

Kafka的存储机制和可靠性

Kafka存储机制前言一、Kafka 存储选择二、Kafka 存储方案剖析三、Kafka 存储架构设计四、Kafka 日志系统架构设计4.1、Kafka日志目录布局4.2、Kafka磁盘数据存储五、Kafka 可靠性5.1、Producer的可靠性保证5.1.1、kafka 配置为 CP(Consistency & Partition tolerance)系统5…

【正厚软件】0基础学IT,来Linux的发展历史吧

本文来源&#xff1a;正厚软件沙老师 Linux 的发展历史 1991年林纳斯.托瓦兹开发了Linux内核&#xff0c;宣布它的诞生。 1999年&#xff0c;IBM宣布于RedHat公司建立伙伴关系&#xff0c;以确保RedHat在IBN机器上的正确运行。 2001年&#xff0c;IBM决定投入10亿美元扩大Linux…

光源基础(4)——如何选择光源及各种打光结构

如何选择和设计光源方案 打光的首要目的是把目标显现出来&#xff0c;同时把背景和干扰信息尽可能地过滤掉或者淡化&#xff0c;这样就可以得到有利于处理的图像&#xff0c;整个系统的精度和稳定性也可以得到必要的保证。 基本思路 如右图所示,光照射到物体表面之后,会发生一系…

Cadence Allegro PCB设计88问解析(十九) 之 Allegro中文字大小设置

个学习信号完整性仿真的layout工程师 在PCB投板之前&#xff0c;经常会进行丝印调整。当然有的单板设计&#xff0c;比如手机这种高密度单板是没有丝印的。但是在绝多数的PCB上是添加丝印的&#xff0c;为了方便前期的测试。丝印也就是我们常说的器件的位号&#xff0c;还包括一…

线上线程池配置错误导致服务故障

背景 某个早高峰&#xff0c;服务大量抛出线程拒绝的异常&#xff0c;同时没有触发自动扩容&#xff0c;损失了大量请求&#xff0c;影响了单量 原因分析 5why分析法 1、为什么服务抛出线程拒绝&#xff1f; rpc线程池设置为了256&#xff0c;故障期间线程处理慢&#xff0c…

【华秋Nidec尼得科】滑动开关CL-SB的应用

01 什么是滑动开关 滑动开关是用于选择、接通或断开电路的较成熟技术之一, 但由于其纯机电性质, 作为控制或交互机器或过程的某个方面的一种低成本和可靠手段&#xff0c;在现今仍然广为使用。滑动开关被设计成由人的手指驱动, 通常用于工业、商业、电信和消费类应用, 为人与机…

hadoop 3.x大数据集群搭建系列8- 一些辅助的shell脚本

文章目录一. jps查看各个节点后台进程二. 启停hadoop集群三. 群起zookeeper集群脚本zk.sh四. 同步文件五. 启动停止整个集群一. jps查看各个节点后台进程 我们经常需要查看各个节点的进程情况 vi jps.sh #!/bin/bash for i in hp5 hp6 hp7 do echo -------------------------…

MATLAB绘图合集:fcontour绘制隐函数等高线图

本文主要介绍隐函数等高线图的绘制。 说明 fcontour(f) 根据 x 和 y 的默认区间 [-5 5] 和 z 的固定级别值绘制 z f(x,y) 函数的等高线。 fcontour(f,xyinterval) 将在指定区间绘图。要对 x 和 y 使用相同的区间&#xff0c;请将 xyinterval 指定为 [min max] 形式的二元素向量…

单视频播放量超20万的公开课配套教材,猫书来了~

吹爆、强推、比刷剧还爽、一生推、传疯了&#xff01; 很难想象&#xff0c;网友们会用这些词来形容一个纯分享深度强化学习基础知识的视频课。 在 B 站上搜索 “深度强化学习”&#xff0c;在排名 TOP 10 的相关课程中&#xff0c;有 4 个是王树森老师的 Reinforcement Learni…