MyBatis的一对一映射(八)

本文详细介绍了MyBatis框架中的一对一关联映射,包括嵌套结果和嵌套查询两种方式,以及如何使用association元素实现。通过具体实例展示了如何在User和IdCard表间建立关联,实现数据的高效查询。

年轻的时候,遇见了一个人,便以为余生再没有江湖,后来,才懂,她才是江湖的起源。

上一章简单介绍了MyBatis的动态Sql查询(七),如果没有看过,请观看上一章

一. MyBatis的一对一映射

在业务开发中,常常会遇到关联联系的,如表与表之间的一对一关系。如,员工与员工的身份证号, 这就是典型的一对一。 可以与Hibernate的一对一 区别理解。
Hibernate的一对一映射地址为: https://blog.youkuaiyun.com/yjltx1234csdn/article/details/83241189

员工表 User:
有图片

身份证表 IdCard:

在这里插入图片描述

其中,IdCard 表中的 uid 并不是外键,只是User 表中id 相对应的那个字段, 值完全一样,但并不用外键,避免删除和修改时与User 表有太大的影响。

其所对应的实体类为:

User.java

package com.yjl.pojo;

/**
 @author:yuejl
 @date: 2019年6月15日 上午11:11:02
 @Description Mybatis 使用的基本类 User
*/
public class User {
	/**
	 * @param id id编号,自增
	 * @param name 姓名
	 * @param age 年龄
	 * @param sex 性别
	 * @param description 描述
	 */
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
	private String description;
	
	//引入id card 的关联类型.
	private IdCard idCard;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public IdCard getIdCard() {
		return idCard;
	}
	public void setIdCard(IdCard idCard) {
		this.idCard = idCard;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", description=" + description
				+ ", idCard=" + idCard + "]";
	}
}

IdCard.java 类:

package com.yjl.pojo;
/**
 @author: yuejl
 @date: 2019年7月5日 下午12:41:47
 @Description 类的相关描述
*/
public class IdCard {
	/**
	 * @param uid 身份证唯一标识符
	 * @param idNum 身份证标识符
	 */
	private Integer id;
	private String idNum;
	
	//引入员工的属性
	private User userId;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getIdNum() {
		return idNum;
	}
	public void setIdNum(String idNum) {
		this.idNum = idNum;
	}
	public User getUserId() {
		return userId;
	}
	public void setUserId(User userId) {
		this.userId = userId;
	}
	@Override
	public String toString() {
		return "IdCard [id=" + id + ", idNum=" + idNum + ", userId=" + userId + "]";
	}
}

二. ResultMap 元素

resultMap 中所具有的元素有:


	<resultMap>
		<!--构造函数-->
		<constructor>
			<!--主键的-->
			<idArg />
			<!--普通属性-->
			<arg/>
		</constructor>
		<!--属性主键-->
		<id />
		<!--普通属性 result-->
		<result />
		<!--一对一关联查询-->
		<association />
		<!---一对多关联查询-->
		<collection />
		<!--鉴别器-->
		<discriminator javaType="">
			<case value=""></case>
		</discriminator>
	</resultMap>

id,result 前面已经讲解过了, 下面讲解一下 constructor 和 association, collection和discriminator 后面章节会讲。

constructor 为构造参数, 在User 表中添加 构造方法, 参数为 id,普通属性有 name 和sex。 手动添加空构造方法。

	public User(){
		
	}
	public User(Integer id,String name,String sex){
		this.id=id;
		this.name=name;
		this.sex=sex;
	}

接口为:

public User getById(int id);

则以前的id,result 为:

<resultMap type="user" id="userResultMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
</resultMap>
<!-- 嵌套结果 -->
	<select id="getById" parameterType="int" resultMap="userResultMap">
		select * from user where id=#{id}
</select>

则可以改成:

<resultMap type="user" id="userResultMap">
		<constructor>
			<!--顺序与构造方法的参数顺序必须一样。 javaType 必须填写。-->
			<idArg javaType="int" column="id" />
			<arg javaType="string" column="name"/>
			<arg javaType="string" column="sex"/>
		</constructor>
</resultMap>

其中, javaType 如果是Integer, 则可以写成’int’, 如果类型是 int,则可以写成’_int’ ,字符串 为’string’.
注意,不要用name 节点. 3.4.3版本之后,才添加了注解。

三. 一对一关联映射

一对一关联映射有两种方式,一种是嵌套结果的,一种是嵌套查询的,都是通过assocation 元素来完成的。 下面会重点介绍一下。

三.一 嵌套结果的一对一查询

嵌套结果,就是将关联的表,即user,idcard 表进行连接查询,将所有的查询结果放置在一个结果集里面,Mybatis 会将这个结果集进行分类组装成新的对象。

接口:

public User getByIdWithResult(@Param(value="id") int id);

sql 语句:

<resultMap type="user" id="userResultMapWithResult">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		<!--property 为属性, 注意,一定不要忘记写 javaType 来指明构造哪个实体类-->
		<association property="idCard" javaType="idCard">
			<!--内部为 连接类 IdCard 中的属性 和关联表IdCard 中的字段-->
			<id property="id" column="id"/>
			<result property="idNum" column="idnum"/>
		</association>
	</resultMap>
<select id="getByIdWithResult" parameterType="int" resultMap="userResultMapWithResult">
		<!--关联的sql语句-->
		select * from user u,idCard i where u.id=i.id and u.id=#{id}
</select>

测试方法:

@Test
	public void findByIdWithResultTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		User user=userMapper.getByIdWithResult(1);
		System.out.println(user);
	}

测试运行,控制台打印:

有图片

会发现 IdCard 中的uid 没有值, 那是因为 在实体类 IdCard 中并没有 uid 这个属性。 在IdCard 中也应该添加一个private User user 即User 表的引用,来达到双向关联的目的。 既可以从员工查到IdCard, 也可以从IdCard 查找到对应的员工。 用法一样,故只用一个来举例。

三.二 嵌套查询 用select引入其他空间的查询语句

接口:

public User getByIdWithSelect(int id);

sql语句:

<resultMap type="user" id="userResultMapWithSelect">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		
<!--用了一个column,表示要传入的是哪一个参数的值, select 指明的是哪一个命名空间的哪一条语句-->
		<association property="idCard" javaType="idCard" 
		column="id" select="com.yjl.mapper.IdCardMapper.findByUserId">
		</association>
</resultMap>
<select id="getByIdWithSelect" parameterType="int" resultMap="userResultMapWithSelect">
		<!--是单语句-->
		select * from user u where u.id=#{id}
</select>

IdCardMapper.java 中有一个接口:

public IdCard findById(int id);

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.yjl.mapper.IdCardMapper">
	<resultMap type="idCard" id="idCardResultMap">
		<id property="id" column="id"/>
		<result property="idNum" column="idNum"/>
	</resultMap>
	<!-- 嵌套结果 -->
	<select id="findById" parameterType="int" resultMap="idCardResultMap">
		select * from idCard where id=#{id}
	</select>
	
	<!-- 嵌套查询的sql, 没有对应的接口,传入的参数为int 类型 -->
	<select id="findByUserId" parameterType="int" resultMap="idCardResultMap">
		select * from idCard where uid=#{id}
	</select>
</mapper>

测试方法为:

@Test
	public void findByIdWithSelectTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		User user=userMapper.getByIdWithSelect(1);
		System.out.println(user);
	}

有图片

可以看出,进行了两条 sql语句的查询。

谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

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

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

打赏作者

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

抵扣说明:

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

余额充值