JavaEE简单实例——MyBatis的一对一映射的嵌套查询的简单介绍和基础配置
简单介绍:
在前一章我们介绍了关于MyBatis的多表查询的时候的对应关系,其中有三种对应关系,分别是一对一,一对多,多对多的关系。如果忘记了这三种方式的对应形式可以去前面看看,一定要记住这三种映射关系的图表形式,以及在Java中的以类的形式存在的嵌套关系。这次我们来详细的讲解一对一关系的详细使用方法。
在一对一映射关系的查询中,需要使用到<assciaition>元素,它提供了一系列的用于维护表与表之间关系的属性:
property:用于指定映射关系到实体类对象的属性,与表字段一一对应
column:用于指定表中与对象的属性对应的字段。使用column和property可以完成数据表字段和实体类属性的映射关系。
javaType:用于指定映射到实体类属性值的数据类型
jdbcType:用于指定数据表中对应字段的类型
fetchType:用于指定在关联查询时是否启动延迟加载,fatchType有属性有两个值,lazy和eager两个属性值,默认为lazy。
select:用于指定引入嵌套查询的子SQL语句。
typeHandler:用于指定一个类处理器
<assciaition>是resultMap的子元素,也就是说要使用这个元素需要手动的指定自定义映射规则,并且在我们做多表查询的时候有两种配置方法,嵌套查询和嵌套结果集,我们先讲解嵌套查询
嵌套查询的方式进行多表查询:
嵌套查询的核心理念:将一条查询语句的结果当作另一条查询语句的查询条件。比如在我们想要查询学生的学生卡的时候,需要首先查询学生的信息,得到这个学生的所有信息之后找出学籍号这一列,然后用这个数据再去查询学生卡,在SQL语句中就是这样的:
![]()
查询结果就是这样的:

而我们要做就是将子查询的查询结果分离出我们要的列的信息之后,再把这个信息传递给父查询作为查询参数进行进一步查询,最终得出我们想要的结果
前期准备:
首先我们需要两个数据库,一个用来存储学生的相关信息,一个用来存储学生卡的相关信息:


SQL语句:
show databases ;
use mybatis;
show tables ;
create table user(id int COMMENT 'id信息',name varchar(10) COMMENT '姓名',sex varbinary(3) COMMENT '性别',id_card int COMMENT 'id号码'
);
# 这两张表使用id_card字段形成一对一的关系
insert into user values (1,'张三','男',1),(2,'李四','女',2),(3,'王五','男',3);
create table id_card(id_card int COMMENT 'id号码',Information varchar(30) COMMENT '信息'
);
insert into id_card values (1,'我是张三的信息'),(2,'我是李四的信息'),(3,'我是王五的信息');
select * from user;
select * from id_card;
然后就是与之对应的Java实体类,我们需要两个类,一个学生类用来存储学生的相关信息,一个学生卡类用来存储学生的相关信息:
首先是学生卡类:
package com.mybatis.POJO;public class IdCard {private int id_card;private String Information;public IdCard() {}public IdCard(int id_card, String information) {this.id_card = id_card;Information = information;}public int getId_card() {return id_card;}public void setId_card(int id_card) {this.id_card = id_card;}public String getInformation() {return Information;}public void setInformation(String information) {Information = information;}@Overridepublic String toString() {return "IdCard{" +"id_card=" + id_card +", Information='" + Information + '\'' +'}';}
}
然后是学生类:
package com.mybatis.POJO;public class User{private int id;private String name;private String sex;private IdCard id_card;public User() {}public User(int id, String name, String sex, IdCard id_card) {this.id = id;this.name = name;this.sex = sex;this.id_card = id_card;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public IdCard getId_card() {return id_card;}public void setId_card(IdCard id_card) {this.id_card = id_card;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", sex='" + sex + '\'' +", id_card=" + id_card +'}';}
}
在创建学生类的时候就需要注意了,在我们之前介绍一对一查询的Java类实现的时候曾经说过,在Java中体现一对一的查询就是在本类中定义与之关联的类的对象做为属性。比如在A类中定义B类对象作为属性,在B类中定义A类为属性。形成一种互相包含的属性

关键点在这里:

在学生类里面有一个属性,它的类型是学生卡类,也就是达成了我们之前说过一个类里面包含与之关联的对象作为属性,这里是第一个需要注意的点。
使用方法:
在我们创建完之前的数据库和实体类之后,接下来就是进行我们SQL映射语句的编写了:
在我们的嵌套查询的形式中,需要将子查询和父查询分开来写,也就是需要两条SQL映射语句:
<!-- 首先是子查询--><select id="selectIdCard" parameterType="int" resultType="IdCard">select * from id_card where id_card = #{id};</select>
<!-- 然后是父查询--><select id="selectUser" resultMap="MapperIdCard" parameterType="int">select * from user where id = #{id};</select><resultMap id="MapperIdCard" type="User"><result column="name" property="name"/><result column="id" property="id"/><result column="sex" property="sex"/><association property="id_card"column="id_card"javaType="IdCard"select="mappers.NestedSelect.selectIdCard"/></resultMap>
我们来解释一下上面的SQL映射文件的片段:
最上面的SQL映射语句是子查询,也就是对应了我们完整的SQL语句中的这个位置:
传递的参数就是int类型,就是要根据这个值查询,返回的类型是IdCard也就是是这个值:

子查询就是由这些组成的,然后关键在于夫查询:
父查询的SQL语句对应完整的SQL语句如下:

SQL语句的传入参数的属性是int类型,也就是要根据这个值去查询学生信息,然后从学生信息中获取到学生卡号信息,再用学生卡号信息去查询学生卡信息,具体的参数的流向如下图所示:
红色的箭头指向的是参数的传递,蓝色的箭头指向的是结果集的封装。那么最后的SQL语句运行结果就是这样的:

其中由两个比较重要的问题,是我们在之后编写自定义映射规则的时候需要解决的:
1.如何从所有的参数中单独拿出id_card列的数据进行传递?
2.如何将结果集封装成IdCard属性并传递给学生类?
然后我们就要开始对我们之前编写的SQL映射文件中的内容进行详细的解释:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口式开发有两个规范: -->
<!--1.接口中方法的名称必须与SQL语句的唯一标识,也就是id的值保持一致,resultType就是接口中返回值的类型,parameterType就是接口中方法的参数的类型-->
<!-- 2.mapper标签的namespace属性必须是接口的全路径,否则在运行的时候会无法找到接口对象的SQL映射文件 -->
<mapper namespace="mappers.NestedSelect"><!-- 根据id查询单条数据--><select id="selectOne" resultType="User" parameterType="int">select *from userwhere id = #{id};</select><!-- 查询所有的数据--><select id="selectAll" resultType="User">select *from user;</select>
<!-- 开始编写关于嵌套查询的内容-->
<!-- 首先是子查询--><select id="selectIdCard" parameterType="int" resultType="IdCard">select * from id_card where id_card = #{id};</select>
<!-- 然后是父查询--><select id="selectUser" resultMap="MapperIdCard" parameterType="int">select * from user where id = #{id};</select><resultMap id="MapperIdCard" type="User"><result column="name" property="name"/><result column="id" property="id"/><result column="sex" property="sex"/><association property="id_card"column="id_card"javaType="IdCard"select="mappers.NestedSelect.selectIdCard"/></resultMap>
</mapper>
首先我们来看父查询中的resultMap部分:

其中在我们的自定义结果集映射的部分,前几个部分都是和之前是一样的,在最后的<association>元素中,property指向的就是我们的一个类里面包含与之关联的对象作为属性,column就是与其他表建立联系的字段,这个值也就是我们传递给子查询的参数的来源,JavaType的值就是一个类里面包含与之关联的对象作为属性的这个与之关联的对象的类,也就是我们的IdCard的类名,最后的select指向的就是子查询的SQL语句的唯一标识:
具体的参数的传递如下面的图式所示:

最终的运行结果就是如下所示:
在数据库中的查询语句如下:

查询结果如下:

代码实现:
最后总结一下完整的代码:
SQL映射文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口式开发有两个规范: -->
<!--1.接口中方法的名称必须与SQL语句的唯一标识,也就是id的值保持一致,resultType就是接口中返回值的类型,parameterType就是接口中方法的参数的类型-->
<!-- 2.mapper标签的namespace属性必须是接口的全路径,否则在运行的时候会无法找到接口对象的SQL映射文件 -->
<mapper namespace="mappers.NestedSelect"><!-- 根据id查询单条数据--><select id="selectOne" resultType="User" parameterType="int">select *from userwhere id = #{id};</select><!-- 查询所有的数据--><select id="selectAll" resultType="User">select *from user;</select>
<!-- 开始编写关于嵌套查询的内容-->
<!-- 首先是子查询--><select id="selectIdCard" parameterType="int" resultType="IdCard">select * from id_card where id_card = #{id};</select>
<!-- 然后是父查询--><select id="selectUser" resultMap="MapperIdCard" parameterType="int">select * from user where id = #{id};</select><resultMap id="MapperIdCard" type="User"><result column="name" property="name"/><result column="id" property="id"/><result column="sex" property="sex"/><association property="id_card"column="id_card"javaType="IdCard"select="mappers.NestedSelect.selectIdCard"/></resultMap>
</mapper>
接口文件:
package mappers;import com.mybatis.POJO.IdCard;
import com.mybatis.POJO.User;import java.util.List;public interface NestedSelect {public User selectOne(int i);public List<User> selectAll();public List<User> selectUser(int i);public List<IdCard> selectIdCard(int i);
}
测试类:
package mappers;import Tools.create;
import com.mybatis.POJO.IdCard;
import com.mybatis.POJO.User;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;public class NestedSelectTest {NestedSelect mapper = null;SqlSession session = null;@Beforepublic void setUp() throws Exception {session = create.createSqlSession();mapper = create.createNestedSelectMappers();}@Testpublic void testSelectOne() {User user = mapper.selectOne(1);System.out.println(user.toString());}@Testpublic void testSelectAll() {for (User user : mapper.selectAll()) {System.out.println(user.toString());}}
// 测试嵌套查询的运行语句@Testpublic void selectUser(){for (User user : mapper.selectUser(2)) {System.out.println(user.toString());}}@Testpublic void selectIdCard(){for (IdCard idCard : mapper.selectIdCard(1)) {System.out.println(idCard.toString());}}
}
运行结果:

注意点:
在这一章节中所需要的注意点就是我们在配置SQL映射文件的时候一定要清晰的理解这些配置项之间的嵌套关系,以及类与类,表与表之间的关系,或者如果不理解的话,至少知道怎么写能出现什么效果。常见的报错就是SQL语句的嵌套关系错误导致的查询结果不正确,如果出现了查询结果不正确,首先去检查映射关系的部分。如果出现了查询不到数据,可以去看看有没有配置之前的驼峰映射,这个配置会影响后续的我们的自定义映射关系的数据,有可能会导致最终的结果查询不到数据。
相关文章:
JavaEE简单实例——MyBatis的一对一映射的嵌套查询的简单介绍和基础配置
简单介绍: 在前一章我们介绍了关于MyBatis的多表查询的时候的对应关系,其中有三种对应关系,分别是一对一,一对多,多对多的关系。如果忘记了这三种方式的对应形式可以去前面看看,一定要记住这三种映射关系的…...
详解指针(进阶版)(1)
前言:总篇章分为(1)和(2),本篇内容包括:指针数组,数组指针,&数组名与数组名的区分 数组传参 ,函数指针,函数指针数组 part 1:指…...
【OJ】盐荒子孙
📚Description: 盐体图 盐是对人类生存具有重要意义的物质之一。当中国古人从肉食为主转向谷食为主的时候,吃盐的需求就发生了,因为动物血肉里面包含有足够人体所需的盐分,而谷 物本身不包含盐分。在长达几十万年的旧石器时代&…...
Java数据结构 —— 手写线性结构(稀疏数组、栈、队列、链表)
目录 稀疏数组 顺序表 链表 单向顺序链表 双向链表 双向循环链表求解约瑟夫环(Joseph) 栈 顺序栈 队列 顺序队列 顺序循环队列 稀疏数组 当一个数组中大部分值为0,或者相同时,可以采用稀疏数组的方式来保存,从而节约存储…...
docker部署gitlab过程中遇到的一些问题记录
文章目录用nginx代理docker部署的gitlab服务密码重置docker0网卡异常离线安装apt的包用nginx代理docker部署的gitlab服务 一般咱们不会去暴露很多端口给外面,所以部署完gitlab后,我希望能够用nginx来代理我们的gitlab服务。 gitlab的docker部署参考这个…...
数组的定义与使用
文章目录 数组的基本概念数组的基本用法数组与方法互操作一、数组的基本概念 数组:可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。 注意:1. 数组中存放的元素其类型相同 2. 数组的空间是连在一起的 3. 每个空间有自己的编号࿰…...
SAP ABAP用程序删除开发KEY
在BASISI系统管理中,用户的开发Key存储在DEVACCESS表中,如果由于审计需要删除一些用户的开发Key,而系统有限制SM30, SE16 or SE16N 等事务码的使用,你就可以通过一个小程序去删除开发Key。 代码如下: REPORT ZBCDEV…...
安卓设备TF卡概率性无法识别问题
现象 使用t卡的设备出货前检测是正常的,放在仓库中或出货后再开机,有概率的机器无法识别,重新插拔或重启无效,拔下来放pc电脑上识别后再插回设备则恢复正常能识别。 设备信息 系统: Android 8.1.0 数量:抽检有12%的设备无法识别 TF卡:SanDisk Ultra 64GB 10 A1 microS…...
linux安装nodejs和微信小程序自动化部署操作
一.运行环境安装 Node.js 并且版本大于 8.0基础库版本为 2.7.3 及以上开发者工具版本为 1.02.1907232 及以上安装node.js(1).下载node包官网地址:https://nodejs.org/en/download/如果英文不好的,可以看中文网站:https://nodejs.org/zh-cn/download/点击上面的进行下载,当然,也…...
JavaScript高级 Proxy Reflect
1. Proxy 1. 监听对象的变化 有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 我们可以通过 Object.defineProperty 来实现 const obj {name: "why",age: 18,height: 1.88 }// 需求: 监听对象属性的所有操作 // 监听属性的操作 // 1.针对…...
Eth-trunk :LACP模式链路聚合实战
Eth-trunk : LACP模式链路聚合实战 需求描述 PC1和PC3数据vlan10 ,网段为192.168.10.0 /24PC2和PC4数据vlan20 ,网段为192.168.20.0 /24确保设备之间互联互通,使用最大互联带宽并没有环路确保相同网段的PC可以互通判断交换机之间的每个端口…...
【第二章 - 线性表之顺序表】- 数据结构(八千字详解)
目录 一、线性表的定义和特点 二、线性表的顺序表示和实现 2.1 - 线性表的顺序存储表示 2.2 - 顺序表中基本操作的实现 三、练习 3.1 - 移除元素 3.2 - 删除有序数组中的重复项 3.3 - BC100 有序序列合并 3.4 - 88.合并两个有序数组 四、顺序表的问题及思考 线性表、…...
【史上最全面esp32教程】RGB彩灯篇
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录rgb彩灯的介绍使用方法连线库操作彩灯变换颜色实验彩灯呼吸灯效果总结提示:以下是本篇文章正文内容,下面案例可供参考 rgb彩灯的介绍 ESP32…...
大规模 IoT 边缘容器集群管理的几种架构-5-总结
前文回顾 大规模 IoT 边缘容器集群管理的几种架构-0-边缘容器及架构简介大规模 IoT 边缘容器集群管理的几种架构-1-RancherK3s大规模 IoT 边缘容器集群管理的几种架构-2-HashiCorp 解决方案 Nomad大规模 IoT 边缘容器集群管理的几种架构-3-Portainer大规模 IoT 边缘容器集群管…...
逆风翻盘拿下感知实习offer,机会总是留给有准备的人
个人背景211本,985硕,本科是计算机科学与技术专业,研究生是自学计算机视觉方向,本科主要做C和python程序设计开发,java安卓开发,研究生主要做目标检测,现在在入门目标跟踪和3d目标检测。无论文&…...
SpringBoot整合阿里云OSS文件上传、下载、查看、删除
SpringBoot整合阿里云OSS文件上传、下载、查看、删除1、开发准备1.1 前置知识1.2 环境参数1.3 你能学到什么2. 使用阿里云OSS2.1 创建Bucket2.2 管理文件2.3 阿里云OSS文档3. 项目初始化3.1 创建SpringBoot项目3.2 Maven依赖3.3 安装lombok插件4. 后端服务编写4.1 阿里云OSS配置…...
对话数字化经营新模式:第2届22客户节(22Day)年猪宴圆满结束!
2023年2月22日,由杭州电子商务研究院联合贰贰网络(集团)、TO B总监联盟等发起举办的“第二届客户节22Day”暨2022年度爱名奖 AM AWARDS颁奖及22年猪宴沙龙活动圆满结束。 (主持人:杜灵芝) 本次沙龙邀请到浙江工业大学管理学院程志…...
数据结构——第二章 线性表(5)——双向循环链表
双向循环链表1.双向循环链表的定义2.双向循环链表的基本操作实现2.1 双向循环链表的初始化操作2.2.双向循环链表的插入操作2.3. 双向循环链表的删除操作1.双向循环链表的定义 单向链表便于查询后继结点,不便于查询前驱结点。为了方便两个方向的查询,可以…...
4面美团软件测试工程师,却忽略了这一点,直接让我前功尽弃
说一下我面试别人时候的思路 反过来理解,就是面试时候应该注意哪些东西;用加粗部分标注了 一般面试分为这么几个部分: 一、自我介绍 这部分一般人喜欢讲很多,其实没必要。大约5分钟内说清楚自己的职业经历,自己的核…...
robot remote server用这个server去远程获取ip
server端配置: 1、安装python环境 2、下载robot remote server 下载地址:https://pypi.python.org/pypi/robotremoteserver/(不要用pip下载,把robotremoteserver.py文件下载下来) 3、首先创建一个目录E:\rfremote\ &a…...
智能网络资源下载器:轻松捕获微信、抖音、小红书等平台内容
智能网络资源下载器:轻松捕获微信、抖音、小红书等平台内容 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 你是否…...
YooAsset实战指南:Unity热更新架构重构与AB包管理
1. 为什么热更新不是“加个插件就能跑”,而是Unity项目上线前必须重做的一次架构手术 在Unity游戏开发里,"热更新"这三个字,听上去像是一键开启的魔法开关——版本发出去了,发现UI错位、数值写反、新活动脚本没加载&…...
终极Python金融数据接口:3步掌握免费高效的A股数据获取方案
终极Python金融数据接口:3步掌握免费高效的A股数据获取方案 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在金融数据分析和量化交易领域,获取准确、及时且成本可控的市场…...
树莓派Zero轻量级数字孪生:Unity实现嵌入式机器人3D可视化控制
1. 这不是“玩具演示”,而是嵌入式机器人开发的数字孪生入口你有没有遇到过这样的场景:手头是一台树莓派Zero驱动的四轮差速小车,电机驱动板接好了,编码器信号也引出来了,PID参数调了三天还是抖得像筛糠;或…...
接口测试入门:从Postman到Python自动化实战指南
1. 别再被“接口测试”四个字吓退——它其实比你想象中更像点外卖很多人第一次听说“接口测试”,脑子里立刻浮现出一串密密麻麻的HTTP请求、满屏curl命令、Postman里层层嵌套的JSON Body,还有动不动就报错的401、500、404……然后默默关掉网页࿰…...
从0到1搭建AI-PPT流水线,支持中英双语自动适配+品牌VI强制注入(含可运行Python脚本+Power Automate配置包)
更多请点击: https://intelliparadigm.com 第一章:从0到1搭建AI-PPT流水线,支持中英双语自动适配品牌VI强制注入(含可运行Python脚本Power Automate配置包) 本方案构建端到端自动化PPT生成流水线,输入结构…...
基于计算机视觉与物联网的智能虫害监测系统设计与实践
1. 项目概述:从“人眼巡查”到“智能感知”的虫害管理革命在农业种植、仓储物流乃至城市绿化管理中,虫害监测一直是一项耗时耗力且高度依赖经验的工作。传统的做法是依靠人工定期巡查,不仅效率低下,覆盖面有限,而且对巡…...
lin诊断功能寻址和静态电流测试方法
lin诊断功能寻址是不会回响应的,不管正响应还是负响应,而且进入会话必须是10 83这种(不知道是不是项目规定)****************************************************************************************************这个数字电流…...
ARGUS:视觉中心化多模态推理框架,实现像素级可验证Chain-of-Thought
1. 项目概述:这不是又一个“多模态大模型”,而是一次视觉推理范式的重新校准ARGUS这个名字,乍看像某个军事侦察系统代号,其实它精准指向了当前多模态AI领域最棘手的痛点——视觉信息在推理链中长期处于“失语”状态。你肯定见过这…...
AI 编程工具选型对比(2026)
面向研发团队的 AI 编程工具全景对比,覆盖功能、定价、适用场景,辅助选型决策。 工具全景 工具 厂商 核心能力 定位 Kiro AWS Agent 级(多步任务/自动化/代码生成+审查) 全栈 AI 开发助手 GitHub Copilot Microsoft/GitHub 代码补全 + Chat + Agent(预览) IDE 内补全为主…...
