MyBatis的关联映射之 一对一(嵌套查询/嵌套结果)

关联映射概述
在实际的开发中,对数据库的操作常常会涉及多张表,这在面向对象中就涉及了对象与对象之间的关联关系 针对多表之间的操作, MyBatis 提供了关联映射,通过关联映射就可以很好地处理对象与对象间的关联关系

这3中关系怎么关联起来呢?

  • 一对一 :在任意一方引入对方主键作为外键
  • 一对多 :在"多"的一方,添加"一"的一方的主键作为外键
  • 多对多 :产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新
    的宇段作为主键

在Java当中,通多随想也可以进行关系描述:如下图所示
在这里插入图片描述
三种关联的描述如下

  • 一对一的关系:就是在本类中定义对方类型的对象,如A类中定义B类类型的属性b, B类中定义A类类型的属性a。
  • 一对多的关系:就是一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a。
  • 多对多的关系:在A类中定义B类类型的集合,在B类中定义A类类型的集合。

一对一关联映射

resultMap元素下包含一个association的子元素,在MyBatis当中就是通过这一子元素来处理一对一关联映射的。MyBatis映射文件Mapper.xml详解 单击前往

在association元素中通常会要配置到以下元素

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

MyBatis 在映射文件中加载关联关系对象主要通过两种方式:嵌套查询和嵌套结果,嵌套查询是指通过执行另外一条 SQL 映射语句来返回预期的复杂类型;嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。
以下案例通过一个人只有一个身份证号码的案例来说明这个一对一的关系:
首先在数据库当中建立一个身份信息表,和个人信息表:其中把身份表的id列引入到个人表当中作为外键。建表后插入俩条数据用于测试

CREATE TABLE tb_idcard( 
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR (18));

INSERT INTO tb_idcard (CODE) VALUES('430481200001011111')
INSERT INTO tb_idcard (CODE) VALUES('430481200001012222')

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)
)

INSERT INTO tb_person(NAME,age,sex,card_id)VALUES('汤姆',20,'男',1);
INSERT INTO tb_person(NAME,age,sex,card_id)VALUES('李红',20,'女',2);

SELECT * FROM tb_person
SELECT * FROM tb_idcard

所有该项目文件的层次如下图:所需要的的包也就是MyBatis的包和数据库驱动包:第一个MyBatis程序,单击前往:
在这里插入图片描述
随后建立其对应的java类:对每一列的列名进行getset封装以及重写toString方法:
IdCard类

package com.lzq.po;
public class IdCard {
	private Integer id;
	private String code;
//getset方法省略
	@Override
	public String toString() {
		return "IdCard [id =" + id + ",code=" + code + "]";
	}
}

Person类

package com.lzq.po;
public class Person {
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
	private IdCard card;
	@Override
	public String toString() {
		return "Person [id =" + id + ",name=" + name + ",age=" + age + ",sex= " + sex + ",card=" + card + "]";
	}
}

嵌套查询

随后在mapper包下进行配置mapper文件:
使用了MyBatis 中的嵌套查询方式进行了个人及其关联的证件信息查询,因为返回的个人对象中除了基本属性外还有一个关联的card属性,所以需要手动编写结果映射。从映射文件PersonMapper.xml中可以看出,嵌套查询的方法是先执行一-个简单的SQL语句,然后在进行结果映射时,将关联对象在<association>元素中使用select属性执行另一条SQL语句(即ldCardMapper.xml中的SQL )。

IdCardMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzq.mapper.IdCardMapper">
  <select id="findCodeById" parameterType="Integer" resultType="IdCard">
	  SELECT * from tb_idcard where id=#{id}
  </select>
</mapper>

PersonMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzq.mapper.PersonMapper">
	<select id="findPersonById" parameterType="Integer"
		resultMap="IdCardWithPersonResult">
		select * from tb_person where id =#{id}
	</select>
	<resultMap type="Person" id="IdCardWithPersonResult">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="age" column="age" />
		<result property="sex" column="sex" />
		<association property="card" column="card_id"
			javaType="IdCard" select="com.lzq.mapper.IdCardMapper.findCodeById" />
	</resultMap>
</mapper>

以及在mybatis-config.xml文件当中进行配置mapper文件:

<mapper resource="com/lzq/mapper/PersonMapper.xml" />
<mapper resource="com/lzq/mapper/IdCardMapper.xml" />

最后在测试类当中编写方法进行测试:
在这里面是将获取session对象的代码进行封装了:参考:核心对象
在这一篇文章最后的就是封装的代码,在编写是导入这个类即可调用MybatisUtils.getSession()

public void findPersonByIdCardTest() {
		SqlSession session = MybatisUtils.getSession();
		Person person = session.selectOne("com.lzq.mapper"+".PersonMapper.findPersonById",1);
		System.out.println(person);
		session.close();
	}

可以看到结果如下所示:
在这里插入图片描述
嵌套结果

虽然使用嵌套查询的方式比较简单,但是从图9中可以看出,MyBatis嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大地消耗数据库性能并且会降低查询效率。为此,我们可以使用MyBatis提供的嵌套结果方式来进行关联查询。
在PersonMapper.xml文件当中添加以下查询方式:使用多表联接查询
MyBatis 嵌套结果的方式只编写了一条复杂的多表关联的 SOL 语句,并且在<association> 元素中继续使用相关子元素进行数据库表字段和实体类属性的一一映射

<select id="findPersonById2" parameterType="Integer"
		resultMap="IdCardWithPersonResult2">
		select p.* ,idcard.code from tb_person p,tb_idcard idcard
		where p.card_id =idcard.id and p.id= #{id}
	</select>
	<resultMap type="Person" id="IdCardWithPersonResult2">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="age" column="age" />
		<result property="sex" column="sex" />
		<association property="card" javaType="IdCard">
			<id property="id" column="card_id" />
			<result property="code" column="code" />
		</association>
	</resultMap>

使用同样的测试方法测试:如下图所示:在使用嵌套结果的方式进行查询的时候只会执行一条SQL语句,
在这里插入图片描述
延迟加载
在使用 MyBatis 换套查询方式进行 MyBatis 关联查询映射时,使用 MyBatis 的延迟加载在一定程度上可以降低运行消耗并提高查询效率 MyBatis 默认没有开启延迅加载,需要在核心配直文件 mybatis-config.xml 中的<settings>元素内进行配直,具体配直方式如下:

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

在映射文件中, MyBatis 关联映射的 <association>元索和<collection>元素中都已默认配置了延迟加载属性 即默认属性 fetchType=“lazy” (属性 fetchType="eager"表示立即力口载),

下一篇 :MyBatis的关联映射之 一对多 和 多对多

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Modify_QmQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值