热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java教程:MyBatis怎样处理一对一关联关系?分步骤介绍

在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人,它们之间的关系模型图

在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人,它们之间的关系模型图,如图1所示。
MyBatis怎样处理一对一关联关系
图1 人与身份证的关联关系

那么使用MyBatis是怎么处理图1中的这种一对一关联关系的呢?在元素中,包含了一个子元素,MyBatis就是通过该元素来处理一对一关联关系的。

在元素中,通常可以配置以下属性:

● property:指定映射到的实体类对象属性,与表字段一一对应;

● column:指定表中对应的字段;

● javaType:指定映射到实体对象属性的类型;

● select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询;

● fetchType:指定在关联查询时是否启用延迟加载。fetchType属性有lazy和eager两个属性值,默认值为lazy(即默认关联映射延迟加载)。

元素的使用非常简单,只需要参考如下两种示例配置即可,具体如下:

<!--方式一&#xff1a;嵌套查询-->
<association property&#61;"card" column&#61;"card_id"
javaType&#61;"com.itheima.po.IdCard"select&#61;"com.itheima.mapper.IdCardMapper.findCodeById" />
<!--方式二&#xff1a;嵌套结果-->
<association property&#61;"card" javaType&#61;"com.itheima.po.IdCard"><id property&#61;"id" column&#61;"card_id" /><result property&#61;"code" column&#61;"code" />
</association>

注意&#xff1a;
MyBatis在映射文件中加载关联关系对象主要通过两种方式&#xff1a;嵌套查询和嵌套结果。嵌套查询是指通过执行另外一条SQL映射语句来返回预期的复杂类型&#xff1b;嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。开发人员可以使用上述任意一种方式实现对关联关系的加载。

了解了MyBatis中处理一对一关联关系的元素和方式后&#xff0c;接下来就以个人和身份证之间的一对一关联关系为例&#xff0c;进行详细讲解。

查询个人及其关联的身份证信息是先通过查询个人表中的主键来获个人信息&#xff0c;然后通过表中的外键&#xff0c;来获取证件表中的身份证号信息。其具体实现步骤如下&#xff1a;

&#xff08;1&#xff09;创建数据表。在mybatis数据库中分别创建名为tb_idcard和tb_person的数据表&#xff0c;同时预先插入两条数据。其执行的SQL语句如下所示&#xff1a;

USE mybatis;
# 创建一个名称为tb_idcard的表
CREATE TABLE tb_idcard( id INT PRIMARY KEY AUTO_INCREMENT,CODE VARCHAR(18)
);
# 插入2条数据
INSERT INTO tb_idcard(CODE) VALUES(&#39;152221198711020624&#39;);
INSERT INTO tb_idcard(CODE) VALUES(&#39;152201199008150317&#39;);
# 创建一个名称为tb_person的表
CREATE TABLE tb_person( id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(32),age INT,sex VARCHAR(8),card_id INT UNIQUE, FOREIGN KEY(card_id) REFERENCES tb_idcard(id)
);
# 插入2条数据
INSERT INTO tb_person(name,age,sex,card_id) VALUES(&#39;Rose&#39;,29,&#39;女&#39;,1);
INSERT INTO tb_person(name,age,sex,card_id) VALUES(&#39;tom&#39;,27,&#39;男&#39;,2);

完成上述操作后&#xff0c;数据库tb_idcard和tb_person表中的数据如图2所示。
MyBatis怎样处理一对一关联关系
图2 tb_idcard和tb_person表

&#xff08;2&#xff09;在Eclipse中创建一个名为chapter09的Web项目&#xff0c;然后引入相关JAR包、log4j日志文件、MybatisUtils工具类以及mybatis-config.xml核心配置文件。项目环境搭建完成后的文件结构&#xff0c;如图3所示。
1624527322485_43.png
图3 项目文件结构

&#xff08;3&#xff09;在项目的com.itheima.po包下创建持久化类IdCard和Person&#xff0c;编辑后的代码&#xff0c;如文件1和文件2所示。

文件1 IdCard.java

package com.itheima.po;/*** 证件持久化类*/public class IdCard {private Integer id;private String code;public Integer getId() {return id;}public void setId(Integer id) {this.id &#61; id;}public String getCode() {return code;}public void setCode(String code) {this.code &#61; code;}&#64;Overridepublic String toString() {return "IdCard [id&#61;" &#43; id &#43; ", code&#61;" &#43; code &#43; "]";}}

文件2 Person.java

package com.itheima.po;/*** 个人持久化类*/public class Person {private Integer id;private String name;private Integer age;private String sex;private IdCard card; //个人关联的证件public Integer getId() {return id;}public void setId(Integer id) {this.id &#61; id;}public String getName() {return name;}public void setName(String name) {this.name &#61; name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age &#61; age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex &#61; sex;}public IdCard getCard() {return card;}public void setCard(IdCard card) {this.card &#61; card;}&#64;Overridepublic String toString() {return "Person [id&#61;" &#43; id &#43; ", name&#61;" &#43; name &#43; ", "&#43; "age&#61;" &#43; age &#43; ", sex&#61;" &#43; sex &#43; ", card&#61;" &#43; card &#43; "]";}}

在上述两个文件中&#xff0c;分别定义了各自的属性以及对应的getter/setter方法&#xff0c;同时为了方便查看输出结果还重写了toString()方法。

&#xff08;4&#xff09;在com.itheima.mapper包中&#xff0c;创建证件映射文件IdCardMapper.xml和个人映射文件PersonMapper.xml&#xff0c;并在两个映射文件中编写一对一关联映射查询的配置信息&#xff0c;如文件3和文件4所示。

文件3 IdCardMapper.xml

<?xml version&#61;"1.0" encoding&#61;"UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace&#61;"com.itheima.mapper.IdCardMapper"><!-- 根据id查询证件信息 --><select id&#61;"findCodeById" parameterType&#61;"Integer" resultType&#61;"IdCard">SELECT * from tb_idcard where id&#61;#{id}</select></mapper>

文件4 PersonMapper.xml

<?xml version&#61;"1.0" encoding&#61;"UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace&#61;"com.itheima.mapper.PersonMapper"><!-- 嵌套查询&#xff1a;通过执行另外一条SQL映射语句来返回预期的特殊类型 --><select id&#61;"findPersonById" parameterType&#61;"Integer" resultMap&#61;"IdCardWithPersonResult">SELECT * from tb_person where id&#61;#{id}</select><resultMap type&#61;"Person" id&#61;"IdCardWithPersonResult"><id property&#61;"id" column&#61;"id" /><result property&#61;"name" column&#61;"name" /><result property&#61;"age" column&#61;"age" /><result property&#61;"sex" column&#61;"sex" /><!-- 一对一&#xff1a;association使用select属性引入另外一条SQL语句 --><association property&#61;"card" column&#61;"card_id" javaType&#61;"IdCard"select&#61;"com.itheima.mapper.IdCardMapper.findCodeById" /></resultMap></mapper>

在上述两个映射文件中&#xff0c;使用了MyBatis中的嵌套查询方式进行了个人及其关联的证件信息查询&#xff0c;因为返回的个人对象中除了基本属性外还有一个关联的card属性&#xff0c;所以需要手动编写结果映射。从映射文件PersonMapper.xml中可以看出&#xff0c;嵌套查询的方法是先执行一个简单的SQL语句&#xff0c;然后在进行结果映射时&#xff0c;将关联对象在元素中使用select属性执行另一条SQL语句&#xff08;即IdCardMapper.xml中的SQL&#xff09;。

&#xff08;5&#xff09;在核心配置文件mybatis-config.xml中&#xff0c;引入Mapper映射文件并定义别名&#xff0c;如文件5所示。

文件5 mybatis-config.xml

<?xml version&#61;"1.0" encoding&#61;"UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 引入数据库连接配置文件 --><properties resource&#61;"db.properties" /><!--使用扫描包的形式定义别名 --><typeAliases><package name&#61;"com.itheima.po" /></typeAliases><!--配置环境 &#xff0c;默认的环境id为mysql --><environments default&#61;"mysql"><!-- 配置id为mysql的数据库环境 --><environment id&#61;"mysql"><!-- 使用JDBC的事务管理 --><transactionManager type&#61;"JDBC" /><!--数据库连接池 --><dataSource type&#61;"POOLED"><property name&#61;"driver" value&#61;"${jdbc.driver}" /><property name&#61;"url" value&#61;"${jdbc.url}" /><property name&#61;"username" value&#61;"${jdbc.username}" /><property name&#61;"password" value&#61;"${jdbc.password}" /></dataSource></environment></environments><!--配置Mapper的位置 --><mappers><mapper resource&#61;"com/itheima/mapper/IdCardMapper.xml" /><mapper resource&#61;"com/itheima/mapper/PersonMapper.xml" /></mappers></configuration>

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

&#xff08;6&#xff09;在com.itheima.test包中&#xff0c;创建测试类MybatisAssociatedTest&#xff0c;并在类中编写测试方法findPersonByIdTest()&#xff0c;如文件6所示。

文件6 MybatisAssociatedTest.java

package com.itheima.test;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import com.itheima.po.Person;import com.itheima.utils.MybatisUtils;/*** Mybatis关联查询映射测试类*/public class MybatisAssociatedTest {/*** 嵌套查询*/&#64;Testpublic void findPersonByIdTest() {// 1、通过工具类生成SqlSession对象SqlSession session &#61; MybatisUtils.getSession();// 2.使用MyBatis嵌套查询的方式查询id为1的人的信息Person person &#61; session.selectOne("com.itheima.mapper." &#43; "PersonMapper.findPersonById", 1);// 3、输出查询结果信息System.out.println(person);// 4、关闭SqlSessionsession.close();}}

在文件6的findPersonByIdTest()方法中&#xff0c;首先通过MybatisUtils工具类获取了SqlSession对象&#xff0c;然后通过SqlSession对象的selectOne()方法获取了个人信息。为了查看结果&#xff0c;这里使用了输出语句输出查询结果信息。最后程序执行完毕时&#xff0c;关闭了SqlSession。

使用JUnit4执行findPersonByIdTest()方法后&#xff0c;控制台的输出结果如图4所示。
MyBatis怎样处理一对一关联关系
图4 运行结果

从图4可以看出&#xff0c;使用MyBatis嵌套查询的方式查询出了个人及其关联的身份证信息&#xff0c;这就是MyBatis中的一对一关联查询。

虽然使用嵌套查询的方式比较简单&#xff0c;但是从图4中可以看出&#xff0c;MyBatis嵌套查询的方式要执行多条SQL语句&#xff0c;这对于大型数据集合和列表展示不是很好&#xff0c;因为这样可能会导致成百上千条关联的SQL语句被执行&#xff0c;从而极大的消耗数据库性能并且会降低查询效率。这并不是开发人员所期望的。为此&#xff0c;我们可以使用MyBatis提供的嵌套结果方式&#xff0c;来进行关联查询。

在PersonMapper.xml中&#xff0c;使用MyBatis嵌套结果的方式进行个人及其关联的证件信息查询&#xff0c;所添加的代码如下所示&#xff1a;

<!-- 嵌套结果&#xff1a;使用嵌套结果映射来处理重复的联合结果的子集 -->
<select id&#61;"findPersonById2" parameterType&#61;"Integer" resultMap&#61;"IdCardWithPersonResult2">SELECT p.*,idcard.codefrom tb_person p,tb_idcard idcardwhere p.card_id&#61;idcard.id and p.id&#61; #{id}
</select>
<resultMap type&#61;"Person" id&#61;"IdCardWithPersonResult2"><id property&#61;"id" column&#61;"id" /><result property&#61;"name" column&#61;"name" /><result property&#61;"age" column&#61;"age" /><result property&#61;"sex" column&#61;"sex" /><association property&#61;"card" javaType&#61;"IdCard"><id property&#61;"id" column&#61;"card_id" /><result property&#61;"code" column&#61;"code" /></association>
</resultMap>

从上述代码中可以看出&#xff0c;MyBatis嵌套结果的方式只编写了一条复杂的多表关联的SQL语句&#xff0c;并且在元素中继续使用相关子元素进行数据库表字段和实体类属性的一一映射。

在测试类MybatisAssociatedTest中&#xff0c;编写测试方法findPersonByIdTest2()&#xff0c;其代码如下所示。

/*** 嵌套结果*/
&#64;Test
public void findPersonByIdTest2() {// 1、通过工具类生成SqlSession对象SqlSession session &#61; MybatisUtils.getSession();// 2.使用MyBatis嵌套结果的方法查询id为1的人的信息Person person &#61; session.selectOne("com.itheima.mapper." &#43; "PersonMapper.findPersonById2", 1);// 3、输出查询结果信息System.out.println(person);// 4、关闭SqlSessionsession.close();
}

使用JUnit4执行findPersonByIdTest2()方法后&#xff0c;控制台的输出结果如图5所示。
MyBatis怎样处理一对一关联关系
图5 运行结果

从图5可以看出&#xff0c;使用MyBatis嵌套结果的方式只执行了一条SQL语句&#xff0c;并且同样查询出了个人及其关联的身份证的信息。

MyBatis延迟加载的配置&#xff1a;

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

<settings><!-- 打开延迟加载的开关 --> <setting name&#61;"lazyLoadingEnabled" value&#61;"true" /> <!-- 将积极加载改为消息加载&#xff0c;即按需加载 --> <setting name&#61;"aggressiveLazyLoading" value&#61;"false"/>
</settings>

在映射文件中&#xff0c;MyBatis关联映射的元素和元素中都已默认配置了延迟加载属性&#xff0c;即默认属性fetchType&#61;“lazy”&#xff08;属性fetchType&#61;"eager"表示立即加载&#xff09;&#xff0c;所以在配置文件中开启延迟加载后&#xff0c;无需在映射文件中再做配置。


推荐阅读
  • java日志框架详解
    Java日志框架详解1.常用日志框架1.1Java常用日志框架类别1.2Java常用日志框架历史1.3两大日志接口阵营1.3.1基于CommonsLogging接口实现的常用日志框 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 从Oracle安全移植到国产达梦数据库的DBA实践与攻略
    随着我国对信息安全和自主可控技术的重视,国产数据库在党政机关、军队和大型央企等行业中得到了快速应用。本文介绍了如何降低从Oracle到国产达梦数据库的技术门槛,保障用户现有业务系统投资。具体包括分析待移植系统、确定移植对象、数据迁移、PL/SQL移植、校验移植结果以及应用系统的测试和优化等步骤。同时提供了移植攻略,包括待移植系统分析和准备移植环境的方法。通过本文的实践与攻略,DBA可以更好地完成Oracle安全移植到国产达梦数据库的工作。 ... [详细]
  • springboot dubbo框架中log4j与slf4jlog4j12日志冲突问题的解决方法
    在基于springboot开发项目中,使用dubbo的RPC框架进行业务拆分,出 ... [详细]
  • 学习mybatis的基础知识:mybatis入门教程(二)
    2019独角兽企业重金招聘Python工程师标准2.3MyBatisprintsql在log4j.properties配置文件中添加如下配置,让mybatis打 ... [详细]
  • 介绍怎样在IntellijIdea中通过创建mavenproject配置MapReduce的编程环境。一、软件环境我使用的软件版本号例如以下:IntellijIdea2017.1M ... [详细]
  • Spring入门第十讲——Hibernate5.0.7+Struts2.3.24+Spring4.2.4三大框架整合开发
    回顾SSH框架至此,Hibernate-5.0.7、Struts-2.3.24和Spring-4.2.4这三个框架,我们已经都过了一遍了。现在,咱就要 ... [详细]
  • 基本信息|根源_SpringBoot 监控统计:SQL监控慢SQL记录Spring监控去广告
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringBoot监控统计:SQL监控慢SQL记录Spring监控去广告相关的知识,希望对你有一定的参考价值。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 我在jboss的耳朵上有一个自定义的登录模块.耳朵的META-INF有一个jboss-app.xml,它指向一个login-service.xml,其中包含一个mbean,该mbean指向一个定 ... [详细]
author-avatar
李伯翔刚瑋嘉军
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有