MyBatis映射关系

2023-11-08

目录

数据库的配置

一.映射关系一对一

1.映射关系 1 对 1-基本介绍

2.映射关系 1 对 1-映射方式

3.应用实例

3.1方式一

方式二:

重点解析:

注解的方式实现

注意事项和细节

二.映射关系多对一

1.基本介绍

2.注意细节

3.映射方式

4.代码实现

4.1数据库表

4.2UserMapper.xml文件

4.3PetMapper.xml文件

注解实现多对 1 映射


数据库的配置

CREATE TABLE person
(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT '',
card_id INT ,
FOREIGN KEY (card_id) REFERENCES idencard(id)
)CHARSET utf8;
-- 创建 mybatis_idencard 表
CREATE TABLE idencard
(
id INT PRIMARY KEY AUTO_INCREMENT,
card_sn VARCHAR(32) NOT NULL DEFAULT '' )CHARSET utf8 ;
INSERT INTO idencard VALUES(1,'111111111111110');
INSERT INTO person VALUES(1,'张三',1);
SELECT * FROM person;
SELECT * FROM idencard

一.映射关系一对一

1.映射关系 1 1-基本介绍

基本介绍
1. 项目中 1 1 的关系是一个基本的映射关系,比如 :Person( ) --- IDCard( 身份证 )
2. 我们看看再 MyBatis 中如何实现 1 1 的处理 .
注意细节
1 1 , 我们这里就研究一下单向 1 1 即可

2.映射关系 1 1-映射方式

映射方式
1. 通过配置 XxxMapper.xml 实现 1 1 [ 配置方式 ]
2. 通过注解的方式实现 1 1 [ 注解方式 ]

3.应用实例

3.1方式一

通过配置 XxxMapper.xml 的方式来实现下面的 1 1 的映射关系,实现
联查询 , 通过 person 可以获取到对应的 idencard 信息

 然后建立各自的javabean--->两个表

 然后我们就可以开始重头戏了开始建立IdenCardMapper.java和IdenCardMapper.xml 

public interface IdenCardMapper {
    //根据id获取到身份证序列号
    public IdenCard getIdenCardById(Integer id);
 <!--
        1、配置/实现//根据id获取到身份证序列号
        2、public IdenCard getIdenCardById(Integer id);
    -->
    <select id="getIdenCardById" parameterType="Integer"
            resultType="IdenCard">
        SELECT * FROM `idencard` WHERE `id` = #{id}
    </select>
    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
    public Person getPersonById(Integer id);
<mapper namespace="com.hong.mapper.PersonMapper">
    <!--
        1、配置/实现public Person getPersonById(Integer id);
        2、完成通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
        3. 为了让小伙伴们理解的更加深刻一点,先用大家容易想到的方式-分析问题-解决问题
        4. 看到如果配置成简单 resultType="Person" 问题就是没有实现级联查询
        5. 自定义resultMap 搞定 映射返回的结果
        6. 因为 getPersonById 最终返回的是 Person对象[只是有级联的对象属性], type仍然配置"Person"
    -->
    <resultMap id="PersonResultMap" type="Person">
        <!--<result property="id" column="id"/>-->
        <!--id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
            1.property="id" 表示person 属性 id ,通常是主键
            2.column="id" 表示对应表的字段
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--association – 一个复杂类型的关联
        1. property="card" 表示 Person对象的 card 属性
        2. javaType="IdenCard" 表示card 属性 的类型
        3. column="id" 是从我们的 下面这个语句查询后返回的字段
        SELECT *  FROM `person`,`idencard` WHERE `person`.id=1
        AND `person`.card_id = `idencard`.id
        -->
        <association property="card" javaType="IdenCard">
            <result property="id" column="id"/>
            <result property="card_sn" column="card_sn"/>
        </association>
    </resultMap>
    <select id="getPersonById" parameterType="Integer"
            resultMap="PersonResultMap">
        SELECT *  FROM `person`,`idencard` WHERE `person`.id = #{id}
        AND `person`.card_id = `idencard`.id
    </select>
</mapper>

方式二:

通过配置 XxxMapper.xml 的方式来实现下面的 1 1 的映射关系,实现级
联查询 , 通过 person 可以获取到对应的 identcard 信息

1. 修改 PersonMapper.java PersonMapper.xml 使用第 2 种映射方式 , 完成 1 1 映射
关系

    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象,方式2
    public Person getPersonById2(Integer id);

    //编写方法,通过card_id 查询得到person对象/数据
    public  Person getPersonByCardId(Integer cardId);
 <!--
        1、通过Person的id获取到Person,包括这个Person关联的IdenCard对象,方式2
        2、public Person getPersonById2(Integer id);
        3. 这里的方式和前面不同.
        1) 先通过 SELECT * FROM `person` WHERE `id` = #{id} 返回 person信息
        2) 再通过 返回的card_id 值,再执行操作,得到IdenCard 数据
    -->
    <resultMap id="PersonResultMap2" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>


        <association property="card" column="card_id"
                     select="com.hong.mapper.IdenCardMapper.getIdenCardById" />
    </resultMap>
    <select id="getPersonById2" parameterType="Integer" resultMap="PersonResultMap2">
        SELECT * FROM `person` WHERE `id` = #{id}
    </select>


</mapper>
1. mybatis第二种方式核心思想: 将这个多表联查,分解成单表操作 , 这样简洁,而且易于维护 ,推荐
2. 而且可以复用你已经写好的方法 -组合
3. property="card": 表示 Person对象的 card 属性
4. column="card_id" 这个是
SELECT * FROM `person` WHERE `id` = #{id}  返回的 字段 card_id 信息/数据
5. 返回的 字段 card_id 信息/数据 作为getIdenCardById入参, 来执行

重点解析

先执行下面的select语句,然后将执行的结果中的card_id传参给getIdenCardById,这个时候我们就直接返回的就是确定这个值的IdenCard的值了。

好,现在我们试着来说明一下啥叫将多表级联变成现在的单表操作。

就是我们先来思考一下MySQL中的多表查询,是不是有一个子查询,你要是知道这个就差不多理解了一半了。我们数据库中的子查询是先将一个查询结果返回给另外一个SQL语句进行操作。那么一对一映射其实本质也是一样,我们先将一个结果作为参数然后传入到一个方法中,这个方法就可以运用这个结果去执行他的操作。

注解的方式实现

通过注解的方式来实现下面的 1 1 的映射关系,实现级联查询 , 通过 person 可以获取到
对应的 identcard 信息
在实际开发中还是 推荐使用配置方式
public interface PersonMapperAnnotation {
    //这里注解实现方法
    //说明: 注解的形式就是对前面xml配置方式的体现
    //这里同学们可以结合前面讲解的xml配置时,加入的注释来理解

    @Select("SELECT * FROM `person` WHERE `id` = #{id}")
    @Results({
          @Result(id = true, property = "id", column = "id"),
          @Result(property = "name", column = "name"),
          @Result(property = "card", column = "card_id",
                  one = @One(select = "com.hong.mapper.IdenCardMapper.getIdenCardById"))
    })
    public Person getPersonById(Integer id);
}

注解的方式也就是xml形式的另外一种体现

public class PersonMapperAnnotationTest {

    //属性
    private SqlSession sqlSession;
    private PersonMapperAnnotation personMapperAnnotation;

    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        personMapperAnnotation = sqlSession.getMapper(PersonMapperAnnotation.class);
    }

    @Test
    public void getPersonById() {

        Person person = personMapperAnnotation.getPersonById(1);
        System.out.println("person----" + person);
        if(sqlSession != null) {
            sqlSession.close();
        }

    }
}

注意事项和细节

1. 表是否设置外键 , MyBatis 进行对象 / 级联映射没有影响
2. 举例 : 去掉 person 表的外键 , 进行测试 , 依然可以获取相应的级联对象

二.映射关系多对一

1.基本介绍

1. 项目中多对 1 的关系是一个基本的映射关系 , 多对 1, 也可以理解成是 1 对多 .
2. User --- Pet : 一个用户可以养多只宠物
3. Dep ---Emp : 一个部门可以有多个员工

2.注意细节

1. 我们直接讲 双向的多对一的关系 ,单向的多对一比双向的多对一简单。
2. 在实际的项目开发中 , 要求会使用双向的多对一的映射关系
3. 说明:什么是 双向的多对一 的关系 : 比如通过 User 可以查询到对应的 Pet, 反过
来,通过 Pet 也可以级联查询到对应的 User 信息 .
4. 多对多的关系,是在多对 1 的基础上扩展即可

3.映射方式

1. 方式 1 :通过配置 XxxMapper.xml 实现多对 1
2. 方式 2 :通过注解的方式实现 多对 1

4.代码实现

4.1数据库表

CREATE TABLE mybatis_user
(id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT '' )CHARSET=utf8 ;
CREATE TABLE mybatis_pet
(id INT PRIMARY KEY AUTO_INCREMENT,
nickname VARCHAR(32) NOT NULL DEFAULT '',
user_id INT ,
FOREIGN KEY (user_id) REFERENCES mybatis_user(id)
)CHARSET=utf8 ;
INSERT INTO mybatis_user
VALUES(NULL,'宋江'),(NULL,'张飞');
INSERT INTO mybatis_pet
VALUES(1,'黑背',1),(2,'小哈',1);
INSERT INTO mybatis_pet
VALUES(3,'波斯猫',2),(4,'贵妃猫',2);
SELECT * FROM mybatis_user;
SELECT * FROM mybatis_pet;

4.2UserMapper.xml文件

<mapper namespace="com.hong.mapper.UserMapper">

    <!--解读
    1、一定要想一想我们前面1-1是如何实现
    2、配置/实现 public User getUserById(Integer id);
    3、思路(1) 先通过user-id 查询得到user信息 (2) 再根据user-id查询对应的pet信息
      并映射到User-List<Pet> pets
    -->
    <resultMap id="UserResultMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--解读:因为pets属性是集合,因此这里需要是collection标签来处理
        1. ofType="Pet" 指定返回的集合中存放的数据类型Pet
        2. collection 表示 pets 是一个集合
        3. property="pets" 是返回的user对象的属性 pets
        4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段对应的值
        -->
        <collection property="pets" column="id" ofType="Pet"
                    select="com.hong.mapper.PetMapper.getPetByUserId"/>
    </resultMap>
    <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
        SELECT * FROM `mybatis_user` WHERE `id` = #{id}
    </select>

</mapper>

4.3PetMapper.xml文件

<mapper namespace="com.hong.mapper.PetMapper">

    <!--
        1、通过User的id来获取pet对象,可能有多个,因此使用List接收
        2、public List<Pet> getPetByUserId(Integer userId);
        3. 完成的思路和前面大体相同.
    -->
    <resultMap id="PetResultMap" type="Pet">
        <id property="id" column="id"/>
        <result property="nickname" column="nickname"/>
        <association property="user" column="user_id"
                     select="com.hong.mapper.UserMapper.getUserById" />
    </resultMap>
    <select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
        SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
    </select>

    <!--说明
        1. 注意体会resultMap带来好处, 直接复用
        2. 实现/配置public Pet getPetById(Integer id);
        3. 通过pet的id获取Pet对象
    -->
    <select id="getPetById"
            parameterType="Integer"
            resultMap="PetResultMap">
        SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
    </select>
</mapper>

注解实现多对 1 映射

需求说明 : 通过注解的方式来实现下面的多对 1 的映射关系,实现级联查询 , 完成前面完成
的任务,通过 User-->Pet 也可 Pet->User , 在实际开发中 推荐使用配置方式来
public interface UserMapperAnnotation {

    //通过id获取User对象

    /**
     * 1. 注解的配置就是对应的Mapper.xml文件配置的,改写
     * 2.
     *     1、一定要想一想我们前面1-1是如何实现
     *     2、配置/实现 public User getUserById(Integer id);
     *     3、思路(1) 先通过user-id 查询得到user信息 (2) 再根据user-id查询对应的pet信息
     *       并映射到User-List<Pet> pets
     *     <resultMap id="UserResultMap" type="User">
     *         <id property="id" column="id"/>
     *         <result property="name" column="name"/>
     *         1. ofType="Pet" 指定返回的集合中存放的数据类型Pet
     *         2. collection 表示 pets 是一个集合
     *         3. property="pets" 是返回的user对象的属性 pets
     *         4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段对应的值
     *         -->
     *         <collection property="pets" column="id" ofType="Pet"
     *                     select="com.hong.mapper.PetMapper.getPetByUserId"/>
     *     </resultMap>
     *     <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
     *         SELECT * FROM `mybatis_user` WHERE `id` = #{id}
     *     </select>
     */

    @Select("SELECT * FROM `mybatis_user` WHERE `id` = #{id}")
    @Results({
          @Result(id = true, property = "id", column = "id"),
          @Result(property = "name", column = "name"),
          //这里请小伙伴注意,pets属性对应的是集合
          @Result(property = "pets",
                  column = "id",
                  many = @Many(select = "com.hong.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    public User getUserById(Integer id);
}
public interface PersonMapperAnnotation {
    //这里注解实现方法
    //说明: 注解的形式就是对前面xml配置方式的体现
    //这里同学们可以结合前面老师讲解的xml配置时,加入的注释来理解

    @Select("SELECT * FROM `person` WHERE `id` = #{id}")
    @Results({
          @Result(id = true, property = "id", column = "id"),
          @Result(property = "name", column = "name"),
          @Result(property = "card", column = "card_id",
                  one = @One(select = "com.hong.mapper.IdenCardMapper.getIdenCardById"))
    })
    public Person getPersonById(Integer id);
}
public interface PetMapperAnnotation {

    //通过User的id来获取pet对象,可能有多个,因此使用List接收

    /**
     * 1、通过User的id来获取pet对象,可能有多个,因此使用List接收
     * 2、public List<Pet> getPetByUserId(Integer userId);
     * 3. 完成的思路和前面大体相同.
     * <resultMap id="PetResultMap" type="Pet">
     * <id property="id" column="id"/>
     * <result property="nickname" column="nickname"/>
     * <association property="user" column="user_id"
     * select="com.hong.mapper.UserMapper.getUserById" />
     * </resultMap>
     * <select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
     * SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
     * </select>
     */

    //id = "PetResultMap" 就是给我们的Results[Result Map] 指定一个名字
    //,目的是为了后面复用
    @Select("SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}")
    @Results(id = "PetResultMap", value = {
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "nickname", column = "nickname"),
            @Result(property = "user",
                    column = "user_id",
                    one = @One(select = "com.hong.mapper.UserMapperAnnotation.getUserById"))

    })
    public List<Pet> getPetByUserId(Integer userId);


    //通过pet的id获取Pet对象, 同时会查询到pet对象关联的user对象

    /**
     * <select id="getPetById"
     * parameterType="Integer"
     * resultMap="PetResultMap">
     * SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
     * </select>
     *
     * @ResultMap("PetResultMap") 使用/引用我们上面定义的 Results[ResultMap]
     */
    @Select("SELECT * FROM `mybatis_pet` WHERE `id` = #{id}")
    @ResultMap("PetResultMap")
    public Pet getPetById(Integer id);
}
一对多的思路:
1.首先我们通过id="getUserById"的select查询获取到user-id对应的所有数据
2.之后也可以通过user-id获取到pet是的信息
3.之后我们也可以通过User的id来获取pet对象,可能有多个,因此使用List接收

简而言之:

        就是我们可以通过主人的id查询到宠物的信息,同时也可以通过宠物的信息查询到主人。

一对一是我先查询一个id,在通过这个id查询到一个信息,而这个信息是可以查询到另外一个表的信息的。而一对多是我通过一个字段查询到这个字段在这个信息里面的所相关的内容(就像一个id可以查询到主人对应的宠物信息),当然是存放在集合之中的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MyBatis映射关系 的相关文章

随机推荐

  • QT 数字转字符串自动补0或者空格,arg()的用法

    十六进制 前面自动补0 QString str QString 1 arg outChar 0xFF 2 16 QLatin1Char 0 int a 0001 十进制 前面自动补0 QString str QString 1 arg a
  • 【双指针】---反转链表

    题目 提供单向链表的头节点head 请反转链表 并返回反转后的链表 分析 同速指针 链表上两个指针 一个先出发 另一个后出发并以相同的速度跟随 通过临时指针让双指针同步前行 思路 源码 package org example pointer
  • 【UE4】蓝图结构体入门及案例

    结构体 结构体是什么 UE4中存在许多不同的变量类型 浮点 布尔 整数 字符串 等等 我们赋予变量意义 用于处理程序的运行 在需要很多意义相同的数据时 我们会应用数组的概念来储存一系列相同类型的数据 但是对于数组中的元素 其的类型是固定不变
  • CVE-2023-3836:大华智慧园区综合管理平台任意文件上传漏洞复现

    文章目录 CVE 2023 3836 大华智慧园区综合管理平台任意文件上传漏洞复现 0x01 前言 0x02 漏洞描述 0x03 影响范围 0x04 漏洞环境 0x05 漏洞复现 1 访问漏洞环境 2 构造POC 3 复现 CVE 2023
  • Java学习----习题总结

    今日习题总结如下 TCP IP分层协议栈 TCP IP协议栈参考模型分为五个层次 应用层 传输层 网络层 链路层和物理层 应用层 是网络应用程序及其应用层协议存留的层次 该层包括了所有与网络相关的高层协议 如文件传输协议 FTP 超文本传输
  • 树莓派上开热点(AP)的三种办法实践结果V2

    树莓派上开热点 AP 的三种办法实践结果 date 2021 08 02 lastmod 2021 09 19 背景 UC2 项目中树莓派大脑和子模块有两种方式连接方式 一种是采用 I2C 总线通过 Arduino 做主从 一种是走 WIF
  • Spring(二)IoC 容器

    IoC 容器 Spring 容器是 Spring 框架的核心 容器将创建对象 把它们连接在一起 配置它们 并管理他们的整个生命周期从创建到销毁 Spring 容器使用依赖注入 DI 来管理组成一个应用程序的组件 这些对象被称为 Spring
  • Arcesium面试体验

    回合 1 能力和技术回合 第一轮有20个Aptitude MCQ 20分钟 和15个技术MCQ 15分钟 分别带有 1和 0 25标记方案 MCQ涵盖了所包含的主题 DSA 操作系统 C C Java基础知识 此后 有2个编码问题 45分钟
  • FFT(快速傅里叶变换)算法

    文章目录 功能 一次FFT的功能 一次IFFT的功能 总体功能 前置技能 多项式的阶 多项式的系数表达式 多项式的点值表达式 复数 复数的基本单位 复数的运算 复平面 复根 定义 几个性质 求多项式乘积的基本步骤 FFT 递归版FFT 核心
  • 【经验分享】Hydra(爆破神器)使用方法

    这个也是backtrack下面很受欢迎的一个工具 参数详解 R 根据上一次进度继续破解 S 使用SSL协议连接 s 指定端口 l 指定用户名 L 指定用户名字典 文件 p 指定密码破解 P 指定密码字典 文件 e 空密码探测和指定用户密码探
  • 大数据Hadoop完全分布式及心得体会

    文章目录 前言 认识hadoop 根据所学知识完成作业 并总结本学期心得体会 一 认识hadoop 二 一课一得作业讲解 实现步骤 1 搭建集群 2 模拟生成新能源车辆数据编写一个程序 3 最终部署 将这些数据写到HDFS中 三 学习收获
  • 概率论中 PDF,PMF,CDF的含义

    概率论中 PDF PMF CDF的含义 在概率论中 我们经常能碰到这样几个概念PDF PMF CDF 这里就简单介绍一下 PDF 概率密度函数 probability density function 在数学中 连续型随机变量的概率密度函数
  • vue的el-form-item标签的label展示名称左右对齐

    vue的el form item是下面的样子
  • 报错Failed to load resource: net::ERR_FILE_NOT_FOUND--浏览器设置跨域

    浏览器报错Failed to load resource net ERR FILE NOT FOUND代表此应用运行需要做跨域 推荐使用火狐浏览器做跨域 之后也用火狐访问 在地址栏输入 about config 点击接受风险并继续 输入se
  • xxl-rpc remoting error(connect timed out), for url : http://172.26.112.1:9999/run

    查看你部署的xxl job admin程序是否部署在外网的 如果是在外网 外网访问不到本地局域网主机 可以使用内网穿透 然后在执行器那里不使用自动获取地址 手动把穿透的地址填进去
  • 1477. 找两个和为目标值且不重叠的子数组

    1477 找两个和为目标值且不重叠的子数组 题目描述 样例1 样例2 样例3 样例4 示例 5 提示 解题思路 代码实现 题目描述 给你一个整数数组 arr 和一个整数值 target 请你在 arr 中找 两个互不重叠的子数组 且它们的和
  • 智慧疫情防控平台(图形化编程mind+)

    本文系湛江市第十七中学星火创客团队及岭南师范学院物联网俱乐部原创部分参赛项目 转载请保留声明 前言 本文章将教会大家如何使用图形化编程制作简易的智慧疫情防控平台 这个项目非常适合于低年级的学生去实践 锻炼自己的逻辑思维和积累一定的项目开发经
  • 嘉兴市人才网即时招聘栏目Ajax动态翻页爬虫练习

    声明 代码仅供技术学习交流 不作其他用途 即时招聘 https www jxrsrc com Index MoreInfo aspx TypeID 34 打开页面后拉到底下点下一页翻页发现浏览器中的地址没有发生变化 分析后这个网站是用ASP
  • 区块链技术在食品供应链领域的应用

    现如今 食品供应链的复杂程度变得越来越高 由此对于食品生产者 供应商和零售店 很难确保整个供应链上产品的真实性 食品安全的问题包含跨供应链认证和食品问题的普及 都是因为缺乏数据和可追踪性 导致事情更加不好 如果需要查询真正的原因 现在则需要
  • MyBatis映射关系

    目录 数据库的配置 一 映射关系一对一 1 映射关系 1 对 1 基本介绍 2 映射关系 1 对 1 映射方式 3 应用实例 3 1方式一 方式二 重点解析 注解的方式实现 注意事项和细节 二 映射关系多对一 1 基本介绍 2 注意细节 3