Mybatis之关联
一、一对多关联
eg:一个用户对应多个订单
建表语句
CREATE TABLE `t_customer` (`customer_id` INT NOT NULL AUTO_INCREMENT, `customer_name` CHAR(100), PRIMARY KEY (`customer_id`)
);
CREATE TABLE `t_order` ( `order_id` INT NOT NULL AUTO_INCREMENT, `order_name` CHAR(100), `customer_id` INT, PRIMARY KEY (`order_id`)
);
INSERT INTO `t_customer` (`customer_name`) VALUES ('张三');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o3', '1');
关联查询:查询custmoer_id=1的用户的所有订单信息和用户信息
select t_customer.customer_id,customer_name,order_id,order_name from t_customer left JOIN t_order on t_customer.customer_id=t_order.customer_id
where t_customer.customer_id=1

Customer实体类:
@Data
public class Customer {private Integer customerId;private String customerName;
//一个顾客的所有订单private List<Order> orderList;
}
Order实体类:
@Data
public class Order {private Integer orderId;private String orderName;private Integer customerId;}
mapper接口:
Customer getCustomerWithOrders(Integer customerId);
xml配置文件:
<resultMap id="CustomerMap" type="Customer"><id property="customerId" column="customer_id"></id><result property="customerName" column="customer_name"></result><collection property="orderList" ofType="Order"><id property="orderId" column="order_id"></id><result property="orderName" column="order_name"></result></collection></resultMap><select id="getCustomerWithOrders" resultMap="CustomerMap">select t_customer.customer_id,customer_name,order_id,order_name from t_customer left JOIN t_order on t_customer.customer_id=t_order.customer_idwhere t_customer.customer_id=#{customerId}</select>
测试:
@Testpublic void test01(){Customer customerWithOrders = orderMapper.getCustomerWithOrders(1);System.out.println(customerWithOrders);}
在“对多”关联关系中,同样有很多配置,但是提炼出来最关键的就是:“collection”和“ofType”
二、对一关联
eg:一个订单对应一个用户
sql语句:查询订单号为1的订单和用户信息
select t_order.* ,t_customer.customer_name from t_order LEFT JOIN t_customer on t_order.customer_id=t_customer.customer_id
where order_id=1;
查询结果:

order实体类新增Customer属性
@Data
public class Order {private Integer orderId;private String orderName;private Integer customerId;//对一关系,用户信息private Customer customer;
}
mapper接口:
Order getOrderWithCustomer(Integer orderId);
xml配置文件:
<resultMap id="OrderMap" type="Order"><id property="orderId" column="order_id"></id><result property="orderName" column="order_name"></result><association property="customer" javaType="Customer"><id property="customerId" column="customer_id"></id><result property="customerName" column="customer_name"></result></association></resultMap><select id="getOrderWithCustomer" resultMap="OrderMap">select t_order.* ,t_customer.customer_name from t_order LEFT JOIN t_customer on t_order.customer_id=t_customer.customer_idwhere order_id=#{orderId};</select>
测试:
@Testpublic void test02(){Order orderWithCustomer = orderMapper.getOrderWithCustomer(1);System.out.println(orderWithCustomer);}
三、OGNL风格的对一关联
<!-- OGNL风格的对一关联--><select id="getOrderWithCustomer2" resultType="Order">select t_order.order_id,t_order.order_name,t_order.customer_id as 'customer.customerId',t_customer.customer_name as 'customer.customerName' from t_order LEFT JOIN t_customer on t_order.customer_id=t_customer.customer_idwhere order_id=#{orderId};</select>
注意起别名时,对象属性costomer.customerId要加上引号
四、多对多关联
eg:一本书对应多个种类,一个种类对应多本书
建立中间表将书和种类对应起来
①根据书的id,查询对应的具体信息和所属种类的信息:
mapper接口:
/*** 根据书的id,查询对应的具体信息和所属种类的信息* @param bookId* @return*/BookEntity selectBookOfCategories(Integer bookId);
xml配置文件:
<resultMap id="BookMap" type="BookEntity"><id property="id" column="book_id"></id><result property="name" column="name"></result><collection property="categoryEntityList" ofType="CategoryEntity"><id property="categoryId" column="category_id"></id><result property="categoryName" column="category_name"></result></collection></resultMap><select id="selectBookOfCategories" resultMap="BookMap">select book_id,category.category_id,category_name,namefrom books,category,category_bookWHERE books.id=category_book.book_idand category_book.category_id=category.category_idand books.id=#{value}</select>
②根据种类的id,查询所有对应书的信息
mapper接口:
CategoryEntity getCategory(Integer id);
xml配置文件
<resultMap id="CategoryMap" type="CategoryEntity"><id property="categoryId" column="category_id"></id><result property="categoryName" column="category_name"></result><collection property="bookEntityList" ofType="BookEntity"><id property="id" column="book_id"></id><result property="name" column="name"></result></collection></resultMap><select id="getCategory" resultMap="CategoryMap">SELECT name,category.category_id ,category_name,book_idfrom books,category,category_bookWHERE books.id=category_book.book_idand category_book.category_id=category.category_idand category.category_id=#{value};</select>
五、分步查询
①分步查询对多关联
根据id查询顾客=>设置resultMap=>collection中的select指定OrderMapper.xml中的根据顾客id查询所有订单的select语句=>column指定传参(顾客id)
CustomerMapper.xml
<resultMap id="CustomerMap" type="Customer"><id property="customerId" column="customer_id"></id><result property="customerName" column="customer_name"></result><collection property="orderList" select="com.iflytek.mapper.OrderMapper.selectOrderListById" column="customer_id"></collection>
</resultMap><select id="getOrderListByCustomerId" resultMap="CustomerMap">select * from t_customer where customer_id=#{id}
</select>
OrderMapper.xml
<select id="selectOrderListById" resultMap="OrderMap0">select * from t_order where customer_id=#{value}
</select>
<resultMap id="OrderMap0" type="Order"><id property="orderId" column="order_id"></id><result property="orderName" column="order_name"></result>
</resultMap>
关系总览:

②分步查询对一关联
OrderMapper.xml
根据订单id查询订单具体信息=>association标签中的select指定CustomerMapper.xml中的根据customer_id查询顾客信息的slecect语句=>column指定传参customer_id
<resultMap id="OrderMap2" type="Order"><id property="orderId" column="order_id"></id><result property="orderName" column="order_name"></result><association property="customer" select="com.iflytek.mapper.CustomerMapper.getCustomerById" column="customer_id"></association></resultMap><select id="getOrderAndCustomer" resultMap="OrderMap2">select * from t_order where order_id=#{orderId}</select>
CustomerMapper.xml
根据用户id查询用户具体信息
<resultMap id="CustomerMap0" type="Customer"><id property="customerId" column="customer_id"></id><result property="customerName" column="customer_name"></result></resultMap><select id="getCustomerById" resultMap="CustomerMap0">select * from t_customer where customer_id=#{value}
</select>
关系总览:

六、延迟加载
查询到Customer的时候,不一定会使用Order的List集合数据。如果Order的集合数据始终没有使用,那么这部分数据占用的内存就浪费了。对此,我们希望不一定会被用到的数据,能够在需要使用的时候再去查询。
延迟加载的概念:对于实体类关联的属性到需要使用时才查询。也叫懒加载。
yml配置文件中开启懒加载
mybatis:configuration:#开启懒加载lazy-loading-enabled: true
测试:
@Test
public void testSelectCustomerWithOrderList() throws InterruptedException {//对多关联Customer customer = mapper.selectCustomerWithOrderList(1);// 这里必须只打印“customerId或customerName”这样已经加载的属性才能看到延迟加载的效果// 这里如果打印Customer对象整体则看不到效果System.out.println("customer = " + customer.getCustomerName());// 先指定具体的时间单位,然后再让线程睡一会儿TimeUnit.SECONDS.sleep(5);List<Order> orderList = customer.getOrderList();for (Order order : orderList) {System.out.println("order = " + order);}
}
效果:刚开始先查询Customer本身,需要用到OrderList的时候才发送SQL语句去查询
DEBUG 11-30 11:25:31,127 ==> Preparing: select customer_id,customer_name from t_customer where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:31,193 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:31,314 <== Total: 1 (BaseJdbcLogger.java:145)
customer = c01
DEBUG 11-30 11:25:36,316 ==> Preparing: select order_id,order_name from t_order where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:36,316 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:36,321 <== Total: 3 (BaseJdbcLogger.java:145)
order = Order{orderId=1, orderName='o1'}
order = Order{orderId=2, orderName='o2'}
order = Order{orderId=3, orderName='o3'}
相关文章:
Mybatis之关联
一、一对多关联 eg:一个用户对应多个订单 建表语句 CREATE TABLE t_customer (customer_id INT NOT NULL AUTO_INCREMENT, customer_name CHAR(100), PRIMARY KEY (customer_id) ); CREATE TABLE t_order ( order_id INT NOT NULL AUTO_INCREMENT, order_name C…...
Labview实现用户界面切换的几种方式---通过VI间相互调用
在做用户界面时我们的程序往往面对的对象是程序使用者,复杂程序如果放在同一个页面中,往往会导致程序冗长卡顿,此时通过多个VI之间的切换就可以实现多个界面之间的转换,也会显得程序更加的高大上。 本文所有程序均可下载ÿ…...
点云从入门到精通技术详解100篇-基于点云和图像融合的智能驾驶目标检测(中)
目录 2.1.2 数据源选型分析 2.2 环境感知系统分析 2.2.1 传感器布置方案分析...
Apache-iotdb物联网数据库的安装及使用
一、简介 >Apache IoTDB (Database for Internet of Things) is an IoT native database with high performance for data management and analysis, deployable on the edge and the cloud. Due to its light-weight architecture, high performance and rich feature set…...
项目管理流程
优质博文 IT-BLOG-CN 一、简介 项目是为提供某项独特产品【独特指:创造出与以往不同或者多个方面与以往有所区别产品或服务,所以日复一日重复的工作就不属于项目】、服务或成果所做的临时性【临时性指:项目有明确的开始时间和明确的结束时间,不会无限期…...
0004.电脑开机提示按F1
常用的电脑主板不知道什么原因,莫名其妙的启动不了了。尝试了很多方法,没有奏效。没有办法我就只能把硬盘拆了下来,装到了另一台电脑上面。但是开机以后却提示F1,如下图: 根据上面的提示,应该是驱动有问题…...
中国电子学会2022年12月份青少年软件编程Scratch图形化等级考试试卷一级真题(含答案)
一、单选题(共25题,共50分) 1. 小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序?(2分) A. B. C. D. 2. 舞台有两个不同的背景,小猫角色的哪个积木能够切换舞台背景?(2分) A. B. C. D. 3. …...
C语言第二弹---C语言基本概念(下)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 C语言基本概念 1、字符串和\02、转义字符3、语句和语句分类3.1、空语句3.2、表达式语句3.3、函数调⽤语句3.4、复合语句3.5、控制语句 4、注释4.1、注释的两种形…...
Java 基础面试题 String(一)
Java 基础面试题 String(一) 文章目录 Java 基础面试题 String(一)String、StringBuffer、StringBuilder 的区别?String 为什么是不可变的?字符串拼接用“” 还是 StringBuilder? 文章来自Java Guide 用于学习如有侵…...
QT中QApplication对象有且只有一个
QT中QApplication对象有且只有一个 QApplication对象 QApplication对象 QApplication是应用程序对象 #include <QApplication> int main(int argc,char* argv[]); {//a对象在一个程序中有且只有一个,QT中要求必须有一个QApplication a(argc,argv…...
HTML CSS 发光字头特效
效果展示: 代码: <html><head> </head><style>*{margin: 0;padding: 0;}body {text-align: center;}h1{/* border: 3px solid rgb(201, 201, 201); */margin-bottom: 20px;}.hcqFont {position: relative;letter-spacing: 0.07…...
4.postman批量运行及json、cvs文件运行
一、批量运行collection 1.各个接口设置信息已保存,在collection中点击run collection 2.编辑并运行集合 集合运行时,单独上传图片时报错。需修改postman设置 二、csv文件运行 可新建记事本,输入测试数据,后另存为新的文本文件&…...
Superset二次开发之集成链路追踪TraceID技术
config.py ##时间-日志级别-完整路径-文件名字-文件行-函数名字-信息 LOG_FORMAT = "%(asctime)s:%(levelname)s:%(pathname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s" 字符串详细信息 格式字符串作用%(name)s日志记录器的名称(记录通道)%(levelno)s日…...
商品详情APP端原数据淘宝数据采集API接口代码接入示例
商品详情APP端原数据API接口(接口接入入口)的作用是提供APP端商品的详细信息,包括价格、描述、图片、折后价、优惠券信息等。通过调用这个API接口,开发者可以获取到APP端商品详情相关的数据,从而进行数据分析ÿ…...
企业官网搭建:打造专业形象的关键步骤
企业官网是企业在数字世界中的门面,搭建一个专业、功能齐全的官网对于企业的形象和业务发展至关重要。以下是一些关键的步骤: 一、确定目标和需求 明确网站的目标、受众和主要功能,为设计和内容提供指导。 二、域名和主机选择 选择易于记忆和…...
Vue2移动端项目使用$router.go(-1)不生效问题记录
目录 1、this.$router.go(-1) 改成 this.$router.back() 2、存储 from.path,使用 this.$router.push 3、hash模式中使用h5新增的onhashchange事件做hack处理 4、this.$router.go(-1) 之前添加一个 replace 方法 问题背景 : 在 Vue2 的一个移动端开发…...
ChatGPT与文心一言:AI助手之巅的对决
随着科技的飞速发展,人工智能助手已经渗透到我们的日常生活和工作中。 而在这个充满竞争的领域里,ChatGPT和文心一言无疑是最引人注目的两款产品。它们各自拥有独特的优势,但在智能回复、语言准确性、知识库丰富度等方面却存在差异。那么&am…...
前端实现贪吃蛇功能
大家都玩过贪吃蛇小游戏,控制一条蛇去吃食物,然后蛇在吃到食物后会变大。本篇博客将会实现贪吃蛇小游戏的功能。 1.实现效果 2.整体布局 /*** 游戏区域样式*/ const gameBoardStyle {gridTemplateColumns: repeat(${width}, 1fr),gridTemplateRows: re…...
文件操作(上)
目录 文件的必要性: 文件分类: 程序文件: 数据文件: 文件的打开与关闭: fopen函数分析: 编辑 FILE*: char*filename: char*mode: fclose函数: 应用: 文件编译 Fgetc Fputc 应用…...
用CHAT写年终总结
问CHAT:写一份政企经理年度总结 CHAT回复:尊敬的同事和领导: 大家好,我是负责政企业务的经理,全年一直坚守在销售一线,为公司带来更多的企业客户并拓展业务领域。感谢领导和同事在工作中的大力支持与热情协…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
