MyBatis入门之一对一关联关系(示例)

【图书介绍】《Spring+Spring MVC+MyBatis从零开始学(视频教学版)(第3版)》-CSDN博客

《Spring+Spring MVC+MyBatis从零开始学(视频教学版)(第3版)》(杨章伟,刘祥淼)【摘要 书评 试读】- 京东图书

在现实生活中,一对一关联关系十分常见。例如,一个学生只有一本学生证,同时一本学生证也只对应一个学生。

那么MyBatis是怎么处理这种一对一关联关系的呢?在本书第7章所讲解的<resultMap>元素中包含一个<association>子元素,MyBatis就是通过该元素来处理一对一关联关系的。

在<association>元素中,通常可以配置以下属性。

  1. property:指定映射到的实体类对象属性,与表字段一一对应。
  2. column:指定表中对应的字段。
  3. javaType:指定映射到实体对象属性的类型。
  4. select:指定引入嵌套查询的子SQL语句,用于关联映射中的嵌套查询。
  5. fetchType:指定在关联查询时是否启用延迟加载,有lazy和eager两个属性值,默认值为lazy(默认关联映射延迟加载)。

<association>元素有如下两种配置方式。

<!--方式一:嵌套查询-->
<association property="card" column="card_id" javaType="com.ssm.po.StudentIdCard"
select="com.ssm.mapper.StudentIdCardMapper.findCodeById"/><!--方式二:嵌套结果-->
<association property="card" javaType="com.ssm.po.StudentIdCard">
<id property="id" column=""card_id"/>
<result property="code" column="code"/>
</association>

注意:MyBatis在映射文件中加载关联关系对象,主要通过两种方式:嵌套查询和嵌套结果。嵌套查询是指通过执行另一条SQL映射语句来返回预期的复杂类型;嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。

【示例9-1】接下来以学生和学生证之间的一对一关联关系为例进一步进行讲解。

查询学生及其关联的学生证信息,其方法是先通过查询学生表中的主键来获取学生信息,然后通过表中的外键来获取学生证表中的学生证号信息。其具体实现步骤如下。

 创建数据表。在db_mybatis数据库中分别创建名为tb_studentidcard和tb_student的数据表,同时预先插入几条数据。其执行的SQL语句如下所示:

#使用数据库db_mybatis
USE db_mybatis;
# 创建一个名称为tb_studentidcard的表
CREATE TABLE tb_studentidcard(
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(8)
);
# 插入两条数据
INSERT INTO tb_studentidcard(CODE) VALUES('18030128');
INSERT INTo tb_studentidcard(CODE) VALUES ('18030135');
# 创建一个名称为tb_student的表(暂时添加少量字段)
CREATE TABLE tb_student(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32),
sex CHAR(1),
card_id INT UNIQUE,
FOREIGN KEY (card_id) REFERENCES tb_studentidcard(id)
);
# 插入两条数据
INSERT INTO tb_student(name, sex, card_id) VALUES('limin','f',1);
INSERT INTO tb_student(name, sex, card_id) VALUES('jack','m',2);

 在IntelliJ IDEA中创建一个名为chapter09的Web项目,然后引入相关JAR包、MybatisUtils工具类,以及db.properties、log4j.properties以及mybatis-config.xml核心配置文件。

 在项目的com.ssm.po包下创建持久化类:学生证类StudentIdCard和学生类Student,编辑后的代码如文件9.1和文件9.2所示。

文件9.1  StudentIdCard.java

01	package com.ssm.po;
02	//学生证类
03	public class StudentIdCard {
04		private Integer id;
05		private String code;
06		public Integer getId() {
07			return id;
08		}
09		public void setId(Integer id) {
10			this.id = id;
11		}
12		public String getCode() {
13			return code;
14		}
15		public void setCode(String code) {
16			this.code = code;
17		}
18		public String toString() {
19			return "StudentIdCard [id=" + id + ", code=" + code + "]";
20		}
21	}

文件9.2  Student.java

01	package com.ssm.po;
02	//学生类
03	public class Student {
04		private Integer id;
05		private String name;
06		private String sex;
07		private StudentIdCard studentIdCard;
08		public Integer getId() {
09			return id;
10		}
11		public void setId(Integer id) {
12			this.id = id;
13		}
14		public String getName() {
15			return name;
16		}
17		public void setName(String name) {
18			this.name = name;
19		}
20		public String getSex() {
21			return sex;
22		}
23		public void setSex(String sex) {
24			this.sex = sex;
25		}
26		public StudentIdCard getStudentIdCard() {
27			return studentIdCard;
28		}
29		public void setStudentIdCard(StudentIdCard studentIdCard) {
30			this.studentIdCard = studentIdCard;
31		}
32		public String toString() {
33			return "Student [id=" + id + ", name=" + name + ", sex=" + sex + 
34	            ", studentIdCard=" + studentIdCard + "]";
35		}
36	}

 在com.ssm.mapper包中创建学生证映射文件StudentIdCardMapper.xml和学生映射文件StudentMapper.xml,并在两个映射文件中编写一对一关联映射查询的配置信息,如文件9.3和文件9.4所示。

文件9.3  StudentIdCardMapper.xml

01	<?xml version="1.0" encoding="UTF-8"?>
02	<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
03		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
04	<mapper namespace="com.ssm.mapper.StudentIdCardMapper">
05		<!--根据id获取学生证信息 -->
06		<select id="findStudentIdCardById" parameterType="Integer" resultType= "StudentIdCard">
07			select * from tb_studentidcard where id=#{id}
08		</select>
09	</mapper>

文件9.4  StudentMapper.xml

01	<?xml version="1.0" encoding="UTF-8"?>
02	<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
03		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
04	<mapper namespace="com.ssm.mapper.StudentMapper">
05		<!--嵌套查询,通过执行一条SQL映射语句来返回预期的特殊类型 -->
06		<select id="findStudentById" parameterType="Integer"
07	        resultMap="StudentIdCardWithStudentResult">
08			select * from tb_student where id=#{id}
09		</select>
10		<resultMap type="Student" id="StudentIdCardWithStudentResult">
11	 	    <id property="id" column="id"/>
12		    <result property="name" column="name"/>
13		    <result property="sex" column="sex"/>
14		    <!-- 一对一,association使用select属性引入另一条SQL语句 -->
15		    <association property="studentIdCard" column="card_id" javaType="StudentIdCard" 
16		    		select="com.ssm.mapper.StudentIdCardMapper.
findStudentIdCardById"/>
17		</resultMap>
18	</mapper>

在上述两个映射文件中,使用了MyBatis中的嵌套查询方式进行学生及其关联的学生证信息查询,因为返回的学生对象中除基本属性外,还有一个关联的studentIdCard属性,所以需要手动编写结果映射。从映射文件StudentMapper.xml中可以看出,嵌套查询的方法是先执行一个简单的SQL语句,然后在进行结果映射时将关联对象在<association>元素中使用select属性引入另一条SQL语句(StudentIdCardMapper.xml中的SQL)。

 在核心配置文件mybatis-config.xml中引入Mapper映射文件并定义别名,如文件9.5所示。

文件9.5  mybatis-config.xml

01	<?xml version="1.0" encoding="UTF-8"?>
02	<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
03		"http://mybatis.org/dtd/mybatis-3-config.dtd">
04	<configuration>
05		<!-- 引入数据库连接配置文件 -->
06		<properties resource="db.properties" />
07		<!-- 使用扫描包的形式定义别名 -->
08		<typeAliases>
09			<package name="com.ssm.po"/>
10		</typeAliases>
11		<environments default="mysql">
12			<environment id="mysql">
13				<transactionManager type="JDBC" />
14				<dataSource type="POOLED">
15					<!--数据库驱动 -->
16					<property name="driver" value="${jdbc.driver}" />
17					<!--连接数据库的ur1 -->
18					<property name="url" value="${jdbc.url}" />
19					<!--连接数据库的用户名 -->
20					<property name="username" value="${jdbc.username}" />
21					<!--连接数据库的密码-->
22					<property name="password" value="${jdbc.password}" />
23				</dataSource>
24			</environment>
25		</environments>
26		<!-- 配置Mapper的位置 -->
27		<mappers>
28			<mapper resource="com/ssm/mapper/StudentIdCardMapper.xml" />
29			<mapper resource="com/ssm/mapper/StudentMapper.xml" />
30		</mappers>
31	</configuration>

在上述核心配置文件中,首先引入了数据库连接的配置文件,然后使用扫描包的形式自定义别名,接下来进行环境的配置,最后配置了Mapper映射文件的位置信息。

 在com.ssm.test包中创建测试类MybatisAssociatedTest,并在类中编写测试方法findStudentByIdTest(),如文件9.6所示。

文件9.6  MybatisAssociatedTest.java

01	package com.ssm.test;
02	import org.apache.ibatis.session.SqlSession;
03	import org.junit.Test;
04	import com.ssm.po.Student;
05	import com.ssm.util.MybatisUtils;
06	public class MybatisAssociatedTest {
07		/*
08		 * 嵌套查询
09		 */
10		@Test
11		public void findStudentByIdTest(){
12			SqlSession sqlSession = MybatisUtils.getSession();
13	     	//使用MyBatis嵌套查询的方法查询id为1的学生信息
14			Student student= sqlSession.selectOne(
15	     		"com.ssm.mapper.StudentMapper.findStudentById",1);
16			System.out.println(student.toString());
17			sqlSession.close();		
18		}
19	}

在文件9.6的findStudentByIdTest()方法中,首先通过MybatisUtils工具类获取SqlSession对象,然后通过SqlSession对象的selectOne()方法获取学生信息,最后关闭SqlSession。执行方法后,控制台的输出结果如图9.1所示。使用MyBatis嵌套查询的方式查询出了学生及其关联的学生证信息,这就是MyBatis中的一对一关联查询。

图9.1  运行结果

虽然使用嵌套查询的方式比较简单,但是嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SOL语句被执行,从而极大地消耗数据库性能,并且会降低查询效率。为此,MyBatis提供了嵌套结果的方式进行关联查询。

在StudentMapper.xml中,使用MyBatis嵌套结果的方式进行学生及其关联的学生证信息查询,所添加的代码如下所示:

<!--嵌套结果,通过嵌套结果映射来处理重复的联合结果的子集 -->
<select id="findStudentById2" parameterType="Integer"
resultMap="StudentIdCardWithStudentResult2">select s.*,sidcard.code from tb_student s,tb_studentidcard sidcardwhere s.card_id=sidcard.id and s.id=#{id}
</select>
<resultMap type="Student" id="StudentIdCardWithStudentResult2"><id property="id" column="id" /><result property="name" column="name" /><result property="sex" column="sex" /><association property="studentIdCard" javaType="StudentIdCard"><id property="id" column="card_id" /><result property="code" column="code" /></association>
</resultMap>

从上述代码中可以看出,MyBatis嵌套结果的方式只编写了一条复杂的多表关联的SQL语句,并且在<association>元素中继续使用相关子元素进行数据库表字段和实体类属性的一一映射。执行结果与图9.1所示的结果相同,但使用MyBatis嵌套结果的方式只执行了一条SQL语句。

注意:在使用MyBatis嵌套查询方式进行关联查询映射时,使用MyBatis的延迟加载在一定程度上可以降低运行消耗并提高查询效率。MyBatis默认没有开启延迟加载,需要在核心配置文件mybatis-config.xml中的<settings>元素内进行配置,具体配置方式如下。

<settings><!--打开延迟加载的开关--><setting name="lazyLoadingEnabled" value="true"/><!--将积极加载改为消极加载,即按需加载--><setting name="aggressiveLazyLoading" value="false" />
</settings>

在映射文件中,MyBatis关联映射的<association>元素和<collection>元素中都已经默认配置了延迟加载属性,即默认属性fetchType="lazy"(属性fetchType="eager"表示立即加载),所以在配置文件中开启延迟加载后,无须在映射文件中再进行配置。

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

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

相关文章

FreeRTOS实时操作系统(1)

前言&#xff1a;FreeRTOS内容较多&#xff0c;分篇发布&#xff0c;较为基础&#xff0c;旨在梳理知识&#xff0c;适合入门的同学 &#xff08;基于正点原子STM32F103开发板V2&#xff09; &#xff08;对于本篇&#xff0c;若有疑问&#xff0c;欢迎在评论区留言&#…

Wooden UI(木头UI纹理按钮边框 背景图标 带PNG素材)

资源包包含以下元素&#xff1a;按钮、图标、框架、复选框等&#xff0c;提供分层的 PSD 文件。 下载&#xff1a;​​Unity资源商店链接资源下载链接 效果图&#xff1a;

橡皮鸭调试法(Rubber Duck Debugging)

橡皮鸭调试法&#xff08;Rubber Duck Debugging&#xff09;是一种编程中的调试技巧&#xff0c;名字来源于一本书《The Pragmatic Programmer》&#xff0c;其中提到程序员可以把问题讲给一只橡皮鸭听&#xff0c;以便在讲解的过程中梳理思路并找到问题的根源。 基本原理&am…

微服务基础架构(图)

微服务基础架构是一种现代化的软件架构模式&#xff0c;旨在将大型复杂的应用程序拆分为多个小型、独立的服务。每个微服务专注于特定的业务功能&#xff0c;可独立开发、部署和扩展。 在微服务基础架构中&#xff0c;通常会使用轻量级的通信机制&#xff0c;如 RESTful API 或…

RISC-V笔记——RVWMO基本体

1. 前言 RISC-V使用的内存模型是RVWMO(RISC-V Weak Memory Ordering)&#xff0c;它是Release Consistency的扩展&#xff0c;因此&#xff0c;RVWMO的基本特性类似于RC模型。 2. RC模型 Release consistency(RC)的提出是基于一个观察&#xff1a;将所有同步操作用FENCE围在一…

升级Unity后产生的Objects内存泄露现象

1&#xff09;升级Unity后产生的Objects内存泄露现象 2&#xff09;能否使用OnDemandRendering API来显示帧率 3&#xff09;Unity闪退问题 4&#xff09;配置表堆内存如何优化 这是第405篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&#xff0c;涵盖了UWA问答…

PHP 8.1.0-dev后门远程命令执行漏洞

#简介 PHP verion 8.1.0-dev于2021年3月28日与后门一起发布&#xff0c;但是后门很快被发现并删除。 #漏洞概述 PHP verion 8.1.0-dev的PHP在服务器上运行&#xff0c;则攻击者可以通过发送User-Agentt标头执行任意代码。 #影响版本 PHP 8.1.0-dev #环境搭建 新建docker…

LLM之RAG实战(四十四)| rag-chatbot:支持Huggingface和Ollama任意模型的多PDF本地RAG方案

特点&#xff1a; 支持本地运行和Kaggle (new)运行支持Huggingface 和Ollama 的任意模型Process multiple PDF inputs.Chat with multiples languages (Coming soon).Simple UI with Gradio. 一、安装使用 1.1 Kaggle&#xff08;推荐&#xff09; Step1&#xff1a;把https…

Android 10.0 Camera2 拍照镜像功能实现

1.前言 在10.0的系统rom定制化开发中,在进行camera2的相关拍照功能开发中,在某些时候会遇到拍照照片 左右镜像的问题,就是照片左半边和右半边是反的,所以就需要在拍照的时候保存图片的时候实现 左右镜像功能,接下来就来分析下拍照保存图片的流程 2.Camera2 拍照镜像功能实…

SQL 干货 | SQL 反连接

最强大的 SQL 功能之一是 JOIN 操作&#xff0c;它提供了一种优雅而简单的方法&#xff0c;将一个表中的每一条记录与另一个表中的每一条记录结合起来。不过&#xff0c;有时我们可能想从一个表中找到另一个表中没有的值。正如我们将在今天的博客文章中看到的&#xff0c;通过包…

图片无损放大工具Topaz Gigapixel AI v7.4.4 绿色版

Topaz A.I. Gigapixel是这款功能齐全的图象无损变大运用&#xff0c;应用可将智能机拍摄的图象也可以有着专业相机的高质量大尺寸作用。你可以完美地放大你的小照片并大规模打印&#xff0c;它根本不会粘贴。它具有清晰的效果和完美的品质。 借助AIGigapixel&#xff0c;您可以…

[Linux网络编程]01-网络基础

此部分为《计算机网络》理论基础&#xff0c;可简要了解 一.计算机网络体系结构 常见的体系结构 OSI体系结构(法律上的国际标准)&#xff1a;物理层->数据链路层->网络层->运输层->会话层->表示层->应用层 TCP/IP体系结构(事实上的国际标准)&#xff1a;…

web网页QQ登录

代码&#xff1a; <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>QQ登录ent</title> </head> <style>ul > li{list-style: none; } a …

13.1 Linux_网络编程_TCP/UDP

字节序 1、概述 什么是字节序&#xff1a; 字节序就是字节的存储顺序&#xff0c;分为大端字节序和小端字节序。 大端字节序&#xff1a;低地址存高位&#xff08;网络&#xff09;小端字节序&#xff1a;低地址存低位&#xff08;主机&#xff09; 检验主机字节序模式&…

【Linux】-权限

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;深入代码世界&#xff0c;了解掌握 Linux 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ​ 一、权限的概念 在Linux 中&…

开源图像超分ECBSR项目源码分析

相关介绍 项目GitHub地址&#xff1a;https://github.com/xindongzhang/ECBSR项目相关论文&#xff1a;https://www4.comp.polyu.edu.hk/~cslzhang/paper/MM21_ECBSR.pdf&#xff08;也可以点这里下载&#xff09;论文解读&#xff1a;Edge-oriented Convolution Block for Re…

秃姐学AI系列之:语义分割 + 数据集 | 转置卷积 + 代码

语义分割 语义分割将图片中的每个像素分类到对应的类别 通常来说现在的会议软件的背景虚化这个功能用的就是语义分割技术 无人车进行路面识别也是语义分割技术 语义分割 vs 实例分割 语义分割将图像划分为若干组成区域&#xff0c;这类问题的方法通常利用图像中像素之间的相关…

基于Multisim三极管B放大系数放大倍数测量电路设计(含仿真和报告)

【全套资料.zip】三极管B放大系数放大倍数测量电路电路设计Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 1.用三个数码管显示B的大小&#xff0c;分别显示个位、十位和百位。 2.显示范围…

【论文精炼分享】GPU Memory Exploitation for Fun and Profit 24‘USENIX

今天分享的论文《GPU Memory Exploitation for Fun and Profit》来自2024年USENIX Security。在本文中&#xff0c;作者团队对 CUDA 程序中的缓冲区溢出问题进行了全面的研究&#xff1a; &#xff08;1&#xff09;对用于访问各种 GPU 内存空间的机制进行了逆向工程&#xff…

纯css 轮播图片,鼠标移入暂停 移除继续

核心 滚动&#xff1a; animation: 动画名称 20s linear infinite normal;停止&#xff1a; animation: 动画名称 20s linear infinite paused; 完整例子&#xff1a; html: <div class"carousel-wrapper"><div class"carousel"><div cl…