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

news2024/10/22 11:37:03

【图书介绍】《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 sidcard
	where 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.coloradmin.cn/o/2220768.html

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

相关文章

CTFHUB技能树之SQL——字符型注入

开启靶场&#xff0c;打开链接&#xff1a; 直接指明是SQL字符型注入&#xff0c;但还是来判断一下 &#xff08;1&#xff09;检查是否存在注入点 1 and 11# 返回正确 1 and 12# 返回错误 说明存在SQL字符型注入 &#xff08;2&#xff09;猜字段数 1 order by 2# 1 order…

InnoDB引擎(架构,事务原理,MVCC详细解读)

目录 架构分析 逻辑存储结构​ 内存结构​ Buffer Pool​ ChaneBuffer 自适应哈希​ LogBuffer​ 磁盘结构​ 后台线程​ 事务原理​ redolog日志 undolog日志​ MVCC​ 三个隐藏字段​ undolog版本链 readview​ RC(读已提交原理分析)​ RR(可重复读原理分析…

MySQL 数据库的备份与恢复:最佳实践与深度探讨

MySQL 数据库的备份与恢复&#xff1a;最佳实践与深度探讨 在现代应用程序和企业系统中&#xff0c;数据库是其核心组件之一&#xff0c;负责存储和管理大量的关键数据。MySQL 作为一种广泛应用的开源数据库管理系统&#xff0c;支持高性能和可扩展性&#xff0c;被广泛应用于…

aws 把vpc残留删除干净

最近忘了把vpc 删干净导致又被收了冤大头钱 在删除vpc 的收发现又eni在使用&#xff0c;但是忘了是哪个资源在占用 先用命令行把占用的资源找出来停掉 使用 AWS 命令行界面&#xff08;CLI&#xff09;来查看 VPC 的使用情况 列出子网&#xff1a; aws ec2 describe-subnets …

每日一道算法题(Leetcode 20)

Whats past is prologue. 凡是过去&#xff0c;皆为序章。 题目 分析 1. 我们可以用栈的结构来解决这道题。 2. 我们使用while循环&#xff0c;每次读取字符串中一个元素进行操作&#xff0c;直到最后读取到 \0为止。 3. 如果遇见 (, [ ,{ 这三种左括号&#xff0c;则把该左…

SWAT-MODFLOW地表水与地下水耦合技术——建议收藏!

原文链接&#xff1a;SWAT-MODFLOW地表水与地下水耦合技术——建议收藏&#xff01;https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247623317&idx1&sn87516da827641ffd124519f929e5da26&chksmfa8da372cdfa2a643b7b806b806b31e025382b9896723d891ffd030…

【Dash】feffery_antd_components 按钮组件的应用

一、feffery_antd_componenet 中的 AntdFloatButton 和 AntdFloatButtonGroup AntdFloatButton 和 AntdFloatButtonGroup 是两个用于创建悬浮按钮和悬浮按钮组的组件。 AntdFloatButton 是单个悬浮按钮组件&#xff0c;它提供了多种属性来定义按钮的外观及行为。AntdFloatBut…

2024双十一最建议买的东西有哪些?双11购物清单大全分享

双十一即将来临&#xff0c;各大品牌都推出了令人心动的优惠活动&#xff0c;让我们能够以更加实惠的价格拥有心仪的好物。其中数码家电的产品&#xff0c;也是迎来了一波降价高潮&#xff0c;因此对于数码家电爱好者而言&#xff0c;双十一是入手的绝佳时机&#xff01;本期我…

HTML+CSS实现点赞效果

效果演示 HTMLCSS实现点赞效果 HTML <div class"heart-container" title"Like"><input type"checkbox" class"checkbox" id"Give-It-An-Id"><div class"svg-container"><svg viewBox&qu…

AD9680(adc直采芯片)使用说明

写这篇文章之前我是没有使用过AD9680的芯片&#xff0c;但是使用过GMS011芯片&#xff08;是国内24S&#xff09;下的公司出来的芯片&#xff0c;寄存器和管脚全对标。 在这里我就大概说一下芯片的说用方法 一、硬件设计 该芯片支持双通道射频直采 支持协议JESD204B 14位 采样…

深度学习面试笔试之前向神经网络-多层感知器、损失函数、反向传播

深度学习面试笔试之前向神经网络-多层感知器、损失函数、反向传播 1. 什么是神经网络1.1 什么是感知器1.2 神经网络的结构1.3 为什么神经网络具有非线性切分能力 2. 神经网络的计算过程2.1 计算过程2.2 随机初始化模型参数2.3 激活函数2.3.1 激活函数有哪些2.3.2 优缺点2.3.3 为…

32.第二阶段x86游戏实战2-遍历技能2(技能二叉树基址)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

爱快路由器配置腾讯云动态域名DDNS详细说明

直白点说就是让爱快路由器自动配置当前公网IP地址给域名&#xff0c;动态域名DDNS不清楚的请自行百度&#xff0c; 这里就可以看见操作日志&#xff0c;那么我们一步一步来配置它吧&#xff0c;首先登录爱快路由器&#xff0c;如下图&#xff1a; 那么腾讯云我们怎么找到ID和…

什么是乐观锁、悲观锁?

什么是乐观锁、悲观锁&#xff1f; 乐观锁&#xff1a;乐观锁和悲观锁是并发控制的两种方式&#xff0c;用来确保在多线程或多用户访问共享资源时&#xff0c;数据的一致性和完整性。 悲观锁&#xff08;Pessimistic Lock&#xff09; 悲观锁假设并发操作会经常发生&#xf…

内卷中的营销大斗法:破局与挑战

如今&#xff0c;各个行业内卷严重&#xff0c;企业在营销领域展开了激烈的大斗法。 内卷&#xff0c;是指一种社会或文化模式在发展到一定阶段后&#xff0c;无法实现自我突破&#xff0c;只能在内部不断精细化、复杂化。商业领域的内卷表现为企业间在产品、服务、价格等方面…

Unity通过高德开放平台获取天气信息

一、注册高德开放平台账号&#xff0c;获取天气接口Key 1、构建自己的应用 网址&#xff1a;https://lbs.amap.com/api/webservice/guide/api/weatherinfo 最终调用api的地址形式&#xff1a; https://restapi.amap.com/v3/weather/weatherInfo?city110101&key<用户…

比瓴科技入选国家工业信息安全发展研究中心SBOM工作组首批成员单位

近日&#xff0c;由开放原子开源基金会主办&#xff0c;开源风险评估与治理技术实验室承办的2024开放原子开源生态大会软件物料清单&#xff08;SBOM&#xff09;分论坛在北京成功举办。 在会议上&#xff0c;国家工业信息安全发展研究中心&#xff08;简称“中心”&#xff0…

Florence-2视觉语言模型简明教程

近年来&#xff0c;计算机视觉领域见证了基础模型的兴起&#xff0c;这些模型无需训练自定义模型即可进行图像注释。我们已经看到了用于分类的 CLIP [2]、用于对象检测的 GroundingDINO [3] 和用于分割的 SAM [4] 等模型——每个模型都在其领域表现出色。但是&#xff0c;如果我…

互动装置如何助力乡村振兴展厅板块划分,实现展示效果最大化?

在这片广袤的土地上&#xff0c;每一个乡村都承载着深厚的历史与文化&#xff0c;如今&#xff0c;随着乡村振兴战略的深入实施&#xff0c;为乡村注入了新的活力&#xff0c;乡村振兴展厅的建设&#xff0c;也成为了这一奋斗目标的有力见证和辅助工具&#xff0c;我们今天就来…