MyBatis的关联映射02

3.一对多

3.1基本介绍

mybatis – MyBatis 3 | XML 映射器

多对一关系也是一个基本的映射关系,多对一,也可以理解为一对多。例如:

User--Pet:一个用户可以有多只宠物

Dep--Emp:一个部门有多个员工

双向的多对一关系:通过User可以查询到对应的所有Pet,反之,通过Pet也可以级联查询到对应的User信息。

多对多的关系就是在多对一的关系上拓展

3.2案例实现

映射方式:

方式1:通过配置映射文件实现多对一

方式2:通过注解的方式实现多对一

需求说明:实现级联查询,通过user的user_id可以查询到User信息和关联的所有pet信息,反之,通过pet的pet_id也可以查询到Pet信息和user的信息

先创建user表和pet表:

-- 创建user表
CREATE TABLE `user`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET=utf8
DESC `user`; -- 创建pet表
CREATE TABLE `pet`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`nickname` VARCHAR(32) NOT NULL DEFAULT '',
`user_id` INT,
FOREIGN KEY (user_id) REFERENCES `user`(id)
)CHARSET=utf8

3.2.1方式一:配置方式

(1)User和Pet实体类

package com.li.entity;

/**
* @author 李
* @version 1.0
*/
public class User {
private Integer id;
private String name;
//因为一个User可以养多个宠物,mybatis使用集合体现这个关系
private List<Pet> pets; //setter、getter方法省略
//双向映射不要使用toString方法,否则会造成栈溢出错误
}
package com.li.entity;

/**
* @author 李
* @version 1.0
*/
public class Pet {
private Integer id;
private String nickname;
//一个pet对应一个user对象
private User user; //setter、getter方法省略
//双向映射不要使用toString方法,否则会造成栈溢出错误
}

(2)UserMapper接口和PetMapper接口

public interface UserMapper {
//通过id获取User对象
public User getUserById(Integer id);
}
public interface PetMapper {
//通过user的id获取pet对象,可能有多个因此使用集合接收
public List<Pet> getPetByUserId(Integer userId);
}

(3)UserMapper.xml,思路:

1)先通过user_id查询得到user信息

2)再根据user_id,查询对应的pet信息,并映射到user-List< Per> pets

多对多的映射思路和一对一的实现类似,不同的使用使用resultMap映射属性时使用的是collecting标签。

<mapper namespace="com.li.mapper.UserMapper">
<!--通过id获取User对象
public User getUserById(Integer id);-->
<select id="getUserById" parameterType="Integer" resultMap="resultUserMap">
SELECT * FROM `user` WHERE id = #{id};
</select> <!--User的属性映射-->
<resultMap id="resultUserMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--1.因为pets属性是一个集合,因此要使用collection标签
2.column="id"的id是SELECT * FROM `user` WHERE id=#{id} 返回的字段
3.ofType="Pet"指定返回的集合存放的数据类型-->
<collection property="pets" column="id" ofType="Pet"
select="com.li.mapper.PetMapper.getPetByUserId"/>
</resultMap>
</mapper>

(4)PetMapper.xml,思路和前面大体相同

<mapper namespace="com.li.mapper.PetMapper">
<!--通过user的id获取pet对象,可能有多个因此使用集合接收
public List<Pet> getPetByUserId(Integer userId);-->
<select id="getPetByUserId" parameterType="Integer" resultMap="resultPetMap">
SELECT * FROM `pet` WHERE user_id =#{userId};
</select> <resultMap id="resultPetMap" type="Pet">
<id property="id" column="id"/>
<result property="nickname" column="nickname"/>
<association property="user" column="user_id"
select="com.li.mapper.UserMapper.getUserById"/>
</resultMap>
</mapper>

(5)测试getUserById()方法,通过UserId查找user对象和联系的pet信息

@Test
public void getUserById() {
User user = userMapper.getUserById(2);
System.out.println("user信息=" + user.getId() + "-" + user.getName());
for (Pet pet : user.getPets()) {
System.out.println("宠物信息=" + pet.getId() + "-" + pet.getNickname());
}
if (sqlSession != null) {
sqlSession.close();
}
}

测试结果:

(6)测试getPetByUserId()方法,通过user的id获取pet对象

@Test
public void getPetByUserId() {
List<Pet> pets = petMapper.getPetByUserId(1);
for (Pet pet : pets) {
System.out.println("UserId=" + pet.getUser().getId()
+ "-PetId=" + pet.getId()
+ "-PetNickName=" + pet.getNickname());
}
if (sqlSession != null) {
sqlSession.close();
}
}

测试结果:

resultMap可以复用,如果有其他方法是返回的和resultMap一样的类型,可以在实现该方法时引用该resultMap。

比如PetMapper接口中新声明了一个方法:

//通过pet的id获取Pet对象,同时查询到pet对象关联的user对象
public Pet getPetById(Integer id);

PerMapper.xml文件:

<!--这里可以直接复用之前的resultPetMap-->
<select id="getPetById" parameterType="Integer" resultMap="resultPetMap">
SELECT * FROM `pet` where id =#{id};
</select>

3.2.2方式二:注解方式

需求说明:通过注解的方式,实现双向的级联查询。

在实际开发中推荐使用配置的方式来做

(1)User和Pet实体类不变

(2)直接在接口中,通过注解实现级联查询

UserMapperAnnotation.java

package com.li.mapper;

import com.li.entity.User;
import org.apache.ibatis.annotations.*; /**
* @author 李
* @version 1.0
* 以注解的方式来实现多对一
*/
public interface UserMapperAnnotation {
//通过id获取User对象
@Select(value = "SELECT * FROM `user` WHERE id = #{id}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
//这里对应返回List类型属性pets,使用注解的many属性
@Result(property = "pets", column = "id",
many = @Many(select =
"com.li.mapper.PetMapperAnnotation.getPetByUserId"))
})
public User getUserById(Integer id);
}

PetMapperAnnotation.java

package com.li.mapper;

import com.li.entity.Pet;
import org.apache.ibatis.annotations.*; import java.util.List; /**
* @author 李
* @version 1.0
*/
public interface PetMapperAnnotation {
//通过user的id获取pet对象
@Select(value = "SELECT * FROM `pet` WHERE user_id =#{userId}")
//配置了id之后就可以复用PetResuleMap
@Results(id = "PetResuleMap", value = {
@Result(id = true, property = "id", column = "id"),
@Result(property = "nickname", column = "nickname"),
@Result(property = "user", column = "user_id",
one = @One(select =
"com.li.mapper.UserMapperAnnotation.getUserById"))
})
public List<Pet> getPetByUserId(Integer userId); //通过pet的id获取pet信息
@Select(value = " SELECT * FROM `pet` where id =#{id}")
@ResultMap("PetResuleMap")//复用上面的PetResuleMap
public Pet getPetById(Integer id);
}

3.3练习

自己设计dept(部门)和emp(雇员)表,它们是一对多的关系。

  1. 通过查询dept,可以级联查询到所有的emp信息
  2. 通过查询emp,也可以级联查询到对应的dept信息
  3. 拓展思考:多对多关系

day08-MyBatis的关联映射02的更多相关文章

  1. 04—mybatis的关联映射

    mybatis的关联映射一对一一对多多对多 一.一对一(一个人只能有一个身份证号) 1.创建表创建表tb_card CREATE TABLE `tb_card` ( `id` int(11) NOT ...

  2. mybatis 一对一关联映射实例

    在实际项目开发中,经常存在一对一的关系,如一个人对应一张身份证信息,这就是一对一的关系.下面是一个简单的实例: 1.建表过程我就省略了,主要是一张Person表,一张IDCard表,其相关属性见步骤2 ...

  3. mybatis之关联映射

    ###mybatis使用之一对一关联映射 1)分析并画ER图.(特别是一对一.一对多.多对多的情况) 2)启动终端数据库,并建库建表,在表中插入值和字段,并查看结果.(后期把navicat用上) 3) ...

  4. Mybatis的关联映射案例

    主要是对之前学习的关联映射做一个案例,自己动手实践一下,可以理解的更好一点. 开发环境 开发工具:idea Java环境: jdk1.8.0_121 数据库:SQLServer 项目结构,里面包含了三 ...

  5. Mybatis的关联映射

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

  6. MyBatis的关联映射和动态SQL

    CREATE TABLE tb_card ( id INT PRIMARY KEY AUTO_INCREMENT, CODE ) ); '); CREATE TABLE tb_person ( id ...

  7. 【Hibernate框架】关联映射(一对一关联映射)

    一.整理思路: 之前,小编总结过Mybatis的关联映射,接下来,再来总结一下hibernate的相关的关联映射,直接上图: 这张图,就是小编整理总结整个Hibernate的关联映射的一个大致思路. ...

  8. Mybatis(四)关联映射

    一. Mybatis关联映射 1 讲数据库中关联关系,主键表与外键表 一对多,多对一,主键表表示一 与外键表表示多 学生与学校的关系,工人与工厂,人员与部门的关系,.... 多        一    ...

  9. SSM框架开发web项目系列(三) MyBatis之resultMap及关联映射

    前言 在上篇MyBatis基础篇中我们独立使用MyBatis构建了一个简单的数据库访问程序,可以实现单表的基本增删改查等操作,通过该实例我们可以初步了解MyBatis操作数据库需要的一些组成部分(配置 ...

  10. MyBatis学习(七)MyBatis关联映射之多对多映射

    对于数据库中的多对多关系建议使用一个中间表来维护关系. 1.创建四张表,分别为用户表,商品表,订单表,中间表. DROP TABLE IF EXISTS `t_user`; CREATE TABLE ...

随机推荐

  1. PyQt4编写界面的两种方式

    PyQt4编写界面的两种方式 应用PyQt4开发图形化界面有两种方式,一种是直接通过QtDesigner通过提供的窗口部件拖拽进行GUI创建,另外一种是直接进行编程实现. 第一种,QtDesigner ...

  2. Hexo博客搭建和简单部署

    title: Hexo博客搭建和简单部署 date: 2020-03-02 12:00:00 categories: - [IT,博客] - [IT,软件,程序] - [IT,软件,搭建与配置] ta ...

  3. Python异步爬虫(aiohttp版)

    异步协程不太了解的话可以去看我上篇博客:https://www.cnblogs.com/Red-Sun/p/16934843.html PS:本博客是个人笔记分享,不需要扫码加群或必须关注什么的(如果 ...

  4. 【敏捷研发系列】前端DevOps流水线实践

    作者:胡骏 一.背景现状 软件开发从传统的瀑布流方式到敏捷开发,将软件交付过程中开发和测试形成快速的迭代交付,但在软件交付客户之前或者使用过程中,还包括集成.部署.运维等环节需要进一步优化交付效率.因 ...

  5. Django三大主流Web框架(django版本安装-项目创建-应用创建-django三板斧)

    目录 一:python三大主流web框架 1.python三大主流Web框架 2:三大主流web框架特点 二:正常运行Django项目所需要知道的注意事项 1.计算机的名称不能有中文,不然bug在哪你 ...

  6. .NET周报【12月第2期 2022-12-15】

    国内文章 九哥聊Kestrel网络编程第一章:开发一个Redis服务器 https://mp.weixin.qq.com/s/HJYnBE-7wbvkAYHxQaq3eQ 我和拥有多个.NET 千星开 ...

  7. cs231n__4.2 神经网络 Neural networks

    CS231n 学习笔记 4.2 神经网络 Neural networks 之前我们已经使用了 很多线性分类函数 现在我们不用单变换的: 我们首先有线性层,然后有这个非线性计算,继而在顶层再加入另一个线 ...

  8. ARL灯塔系统搭建

    前言 ARL(Asset Reconnaissance Lighthouse)资产侦查灯塔,是一个良好的资产收集系统,旨在为渗透测试人员以及安全团队基于企业的网络安全能快速查找到指定企业资产中的脆弱点 ...

  9. 使用IDEA创建一个maven的web项目并部署到tomcat上

    目录 1.创建一个maven项目 2.为项目添加配置文件 3.创建一些类和jsp页面 4.将项目部署到tomcat 1.创建一个maven项目 打开IDEA,File--New--Project 选择 ...

  10. 【JVM故障问题排查心得】「内存诊断系列」Xmx和Xms的大小是小于Docker容器以及Pod的大小的,为啥还是会出现OOMKilled?

    为什么我设置的大小关系没有错,还会OOMKilled? 这种问题常发生在JDK8u131或者JDK9版本之后所出现在容器中运行JVM的问题:在大多数情况下,JVM将一般默认会采用宿主机Node节点的内 ...