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,一经查实,立即删除!

相关文章

RK3576 安卓SDK编译环境搭建

编译 Android14 对机器的配置要求较高: 建议预留500G存储 多分配CPU和内存 建议使用 Ubuntu 20.04 操作系统或更高版本 sudo apt-get updatesudo apt-get install git gnupg flex bison gperf libsdl1.2-dev \ libesd-java libwxgtk3.0-dev squashfs-tools build-essential …

软考-软件设计师(11)-专题强化-算法设计与分析-算法特性、算法表示、算法时间复杂度、算法分类、C语言程序设计

场景 以下为高频考点、知识点汇总。 软件设计师上午选择题知识点、高频考点、口诀记忆技巧、经典题型汇总: 软考-软件设计师(1)-计算机基础知识点:进制转换、数据编码、内存编址、串并联可靠性、海明校验码、吞吐率、多媒体等: 软考-软件设计师(1)-计算机基础知识点:进制…

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…

CentOS 7 安装gcc编译环境

有时需要使用源码安装某个应用程序&#xff0c;有时还需要对源码进行一定程度的修改和定制才能满足业务需求&#xff0c;有时需要在linux环境下开发某个特定功能的c程序&#xff0c;此时都需要用到gcc编译环境&#xff0c;此时就需要安装gcc编译环境。 在 CentOS 7 上安装 C 编…

记一个mysql的坑

数据库表user&#xff0c; 存在一个name字段&#xff0c;字段为varchar类型 现在user表有这么两条记录: idnameageclass1NULL18一班2lisi20二班 假如我根据下面这一条件去更新&#xff0c;更新成功数据行显示为0 update user set age 19 where age 18 and class “一班”…

前端算法:字典and哈希表(力扣1题、349题解法)

目录 一、字典 1.概念 2.特点 3.在JS中如何实现 4.字典用法 使用对象作为字典 使用map 5.应用场景 二、哈希表 1.概念 2.工作原理 3. 在 JavaScript 中的实现 4.哈希表用法 使用 Map 作为哈希表 5.应用场景 三、字典与哈希表的区别 四、力扣算法实战 1.1题 两数…

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 拍照镜像功能实…

JDK17新特性,代码使用,作用详细讲解

目录 1.密封类和密封接口 作用 好处 1. 密封类 2. 密封接口 3. 非密封类 4. 抽象密封类 2.模式匹配for instanceof JDK17前的jdk版本 新JDK17 特性与优点 使用示例 注意事项 作用 3.文本块 作用 好处 代码实例 1. 基本语法&#xff1a; 2.换行和缩进&#xff1a; 3.包…

SQL 干货 | SQL 反连接

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

Vue中v-bind对样式控制的增强—(详解v-bind操作class以及操作style属性,附有案例+代码)

文章目录 v-bind对样式控制的增强2.1 操作class2.1.1 语法2.1.2 对象语法2.1.3 数组语法2.1.4 使用2.1.5 Test 2.2 操作style2.2.1 语法2.2.2 使用2.2.3 Test v-bind对样式控制的增强 2.1 操作class 2.1.1 语法 <div> :class "对象/数组">这是一个div&l…

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

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

【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit(3)

1.问题描述&#xff1a; compatibleSdkVersion升级到5.0.0&#xff08;12&#xff09;之后&#xff0c;调用坐标系转换API&#xff1a;map.convertCoordinate(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02, { longitude: location.longitude, latitude:…

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

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