快速学会MyBatis映射关系一对一

news2025/1/21 18:37:11

文章目录

  • 映射关系一对一
    • 映射关系-官方文档
    • 映射关系1对1-基本介绍
      • 基本介绍
      • 注意细节
    • 映射关系1 对1-映射方式
      • 映射方式
      • 配置Mapper.xml 的方式
        • 方式1
        • 方式2
      • 注解的方式实现
        • 应用实例
        • 总结

映射关系一对一

映射关系-官方文档

文档地址: https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

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

基本介绍

  1. 项目中1 对1 的关系是一个基本的映射关系,比如:Person(人) — IDCard(身份证)
  2. 我们看看再MyBatis 中如何实现1 对1 的处理.

注意细节

1 对1 ,我们这里研究一下单向1 对1。

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

映射方式

  1. 通过配置XxxMapper.xml 实现1 对1 [配置方式]
  2. 通过注解的方式实现1 对1 [注解方式]
  3. 我们用代码实现,应用举例

配置Mapper.xml 的方式

方式1

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

完成功能示意(如下)

person--Person{id=1, name=' 张三', card=IdenCard{id=1,card_sn='111111111111110'}}

创建person 表和idencard 表

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

创建新的module(mybatis-mapping), 相关配置文件可以从上一个module —自己实现MyBatis 底层机制–抽丝剥茧(上)拷贝。

创建com\nlc\entity\IdenCard.java

public class IdenCard {
    private Integer id;
    private String card_sn;

    //通过查询IdenCard 可以级联查询得到person
    private Person person;
    
    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCard_sn() {
        return card_sn;
    }

    public void setCard_sn(String card_sn) {
        this.card_sn = card_sn;
    }

    @Override
    public String toString() {
        return "IdenCard{" +
                "id=" + id +
                ", card_sn='" + card_sn + '\'' +
                ", person=" + person +
                '}';
    }
}

创建com\nlc\entity\Person.java

public class Person {
    private Integer id;
    private String name;
    //因为我们的需要实现一个级联操作, 一个人需要对应一个身份证
    //这里需要直接定义IdenCard对象属性
    private IdenCard card;

    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 IdenCard getCard() {
        return card;
    }

    public void setCard(IdenCard card) {
        this.card = card;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", card=" + card +
                '}';
    }
}

创建com\nlc\mapper\IdenCardMapper.java

public interface IdenCardMapper {
    //根据id获取到身份证序列号
    public IdenCard getIdenCardById(Integer id);
}

创建com\nlc\mapper\IdenCardMapper.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.nlc.mapper.IdenCardMapper">
    <!--
        1、配置/实现//根据id获取到身份证序列号
        2、public IdenCard getIdenCardById(Integer id);
    -->
    <select id="getIdenCardById" parameterType="Integer"
            resultType="IdenCard">
        SELECT * FROM `idencard` WHERE `id` = #{id}
    </select>
</mapper>

创建PersonMapper.java

public interface PersonMapper {
    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
    public Person getPersonById(Integer id);
}

创建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.nlc.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>

创建src\test\java\com\nlc\mapper\IdenCardMapperTest.java

public class IdenCardMapperTest {

    //属性
    private SqlSession sqlSession;
    private IdenCardMapper idenCardMapper;

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

    @Test
    public void getIdenCardById() {
        IdenCard idenCard = idenCardMapper.getIdenCardById(1);
        System.out.println("idenCard--" + idenCard);
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

创建src\test\java\com\nlc\mapper\PersonMapperTest.java , 完成测试

public class PersonMapperTest {

    //属性
    private SqlSession sqlSession;
    private PersonMapper personMapper;

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

    @Test
    public void getPersonById() {
        Person person = personMapper.getPersonById(1);
        System.out.println("person--" + person);
        if (sqlSession != null) {
            sqlSession.close();
        }

    }
}

方式2

通过配置XxxMapper.xml 的方式来实现下面的1 对1 的映射关系,实现级联查询,通过person 可以获取到对应的identcard 信息。
完成功能示意结果(如下)

person--Person{id=1, name=' 张三', card=IdenCard{id=1,card_sn='111111111111110'}}

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

修改PersonMapper.java

public interface PersonMapper {
//通过Person 的id 获取到Person,包括这个Person 管理的IdenCard 对象
public Person getPersonById(Integer id);
//通过Person 的id 获取到Person,包括这个Person 管理的IdenCard 对象,方式2
public Person getPersonById2(Integer id);
}

修改PersonMapper.xml

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

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

修改PersonMapperTest.java 完成测试

    @Test
    public void getPersonById2() {
        Person person = personMapper.getPersonById2(1);
        System.out.println("person---------" + person);
        if (sqlSession != null) {
            sqlSession.close();
        }
    }

注解的方式实现

应用实例

通过注解的方式来实现下面的1 对1 的映射关系,实现级联查询,通过person 可以获取到对应的identcard 信息。
在实际开发中还是推荐使用配置方式。

创建com\nlc\mapper\IdenCardMapperAnnotaion.java

public interface IdenCardMapperAnnotation {
    //根据id获取到身份证
    //这个方法不需要返回任何级联对象
    @Select("SELECT * FROM `idencard` WHERE `id` = #{id}")
    public IdenCard getIdenCardById(Integer id);
}

创建com\nlc\mapper\PersonMapperAnnotation.java

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",
                  //card不对应简单的column,是通过一个方法获取,
                  //card_id是通过以前的方法,返回的一个叫card_id的值,下面的方法是需要一个入参的
                  one = @One(select = "com.nlc.mapper.IdenCardMapper.getIdenCardById"))
        //因为是一对一的映射所以采用one = @One(***)的形式,可以debug看一下他的源码里面的属性
        
    })
    public Person getPersonById(Integer id);
}

创建com\nlc\mapper\PersonMapperAnnotationTest.java 完成测试

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 表的外键, 进行测试, 依然可以获取相应的级联对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/812915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用C语言实现堆排序算法

1.设计思路 排序的思想将一个数组按递增的顺序进行排序&#xff0c;将数组的第一个位置空下&#xff08;下标为0&#xff09;&#xff0c;因为会导致子节点和本身同一个结点&#xff08;i和2i一致&#xff09;&#xff0c;每次堆排序在下标1的位置放上了最大值&#xff0c;然后…

PyTorch - GPU入门教程1

1. 安装GPU版本的PyTorch 登录PyTorch官网https://pytorch.org/&#xff0c;下载对应CUDA版本的PyTorch【不能直接pip install&#xff0c;否则安装上的是CPU版本的】 2. 查看GPU信息 &#xff08;1&#xff09;重要信息 !nvidia-smi我的GPU版本很垃圾&#xff0c;本blog仅…

Qgis二次开发-加载本地离线瓦片地图

1.使用详情 准备离线瓦片地图数据&#xff1a;首先&#xff0c;需要获取离线瓦片地图数据。可以从一些开源地图提供商&#xff08;如OpenStreetMap&#xff09;下载地图切片数据&#xff0c;或者使用一些工具&#xff08;如MapTiler&#xff09;将自己的地图数据切片成瓦片格式…

【ChatGLM_01】ChatGLM2-6B本地安装与部署(大语言模型)

基于本地知识库的问答 1、简介&#xff08;1&#xff09;ChatGLM2-6B&#xff08;2&#xff09;LangChain&#xff08;3&#xff09;基于单一文档问答的实现原理&#xff08;4&#xff09;大规模语言模型系列技术&#xff1a;以GLM-130B为例&#xff08;5&#xff09;新建知识库…

分布式限流方案及实现

优质博文&#xff1a;IT-BLOG-CN 一、限流的作用和意义 限流是对高并发访问进行限制&#xff0c;限速的过程。通过限流来限制资源&#xff0c;可以提高系统的稳定性和可靠性&#xff0c;控制系统的负载&#xff0c;削峰填谷&#xff0c;保证服务质量。 服务限流后的常见处理…

CSS动画——实现波浪摇摆效果...

一、效果展示 以下主要实现四个动画&#xff1a; 元素上下摇摆动画波浪上下摇摆动画气泡上升及消失动画连续气泡右飘动画 二、实现思路 这里主要讲一下波浪上下摇摆动画和连续气泡右飘动画的实现思路 这里拿一张波浪图来举例解释实现波浪动画的思路&#xff1a; 波浪的摇…

14-测试分类

1.按照测试对象划分 ①界面测试 软件只是一种工具&#xff0c;软件与人的信息交流是通过界面来进行的&#xff0c;界面是软件与用户交流的最直接的一层&#xff0c;界面的设计决定了用户对设计的软件的第一印象。界面如同人的面孔&#xff0c;具有吸引用户的直接优势&#xf…

深入理解Gradle构建系统的工作原理

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

《被讨厌的勇气》勇敢的人先享受世界

《被讨厌的勇气》勇敢的人先享受世界 岸见一郎&#xff0c;古贺史健 著 &#xff08;岸见一郎&#xff1a;日本作家&#xff0c;心理学家&#xff0c;哲学家。致力于研究哲学和阿德勒心理学。&#xff09; 渠海霞 译 文章目录 《被讨厌的勇气》勇敢的人先享受世界[toc]第一夜 我…

iOS 应用上架流程详解

iOS 应用上架流程详解 欢迎来到我的博客&#xff0c;今天我将为大家分享 iOS 应用上架的详细流程。在这个数字化时代&#xff0c;移动应用已经成为了人们生活中不可或缺的一部分&#xff0c;而 iOS 平台的 App Store 则是开发者们发布应用的主要渠道之一。因此&#xff0c;了解…

从电容到晶体管的基本介绍

​随着科技的不断进步&#xff0c;元器件在现代电子学中扮演着至关重要的角色。从电容器到晶体管&#xff0c;各种元器件都具有不同的特性和用途。本文将从基础知识出发&#xff0c;介绍电子学中常见的元器件&#xff0c;以及它们在电路中的作用和应用。 电容器 电容器是一种…

CommonCollections6链分析

前面和CC1一样 优点是不限制jdk版本和cc的版本 先开一个ChainedTransformer 然后创LazyMap 我们顺便执行一下避免上面写错 能弹计算器 没问题 后面就是CC6不同的地方了 我们需要一个TiedMapEntry 因为需要一个类调用了get方法 在TiedMapEntry的getValue()方法中调用了get()…

哪些元器件在未来会有更广泛的应用?

随着科技的发展和进步&#xff0c;电子技术已经成为现代社会的重要组成部分。元器件作为电子产品的基本构成单元&#xff0c;其发展和应用对于电子技术的进步和创新有着至关重要的作用。随着人工智能、物联网和智能制造等新兴技术的快速发展&#xff0c;一些元器件已经或者将在…

vue基础-diff算法

vue基础-diff算法 1、根元素改变2、根元素不变 1、根元素改变 同级比较-根元素的变化-整个dom树删除重建 2、根元素不变 同级比较&#xff0c;根元素不变-属性改变更新属性

【计算机网络】HTTP详解

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招工作面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于小林Codeing进行的&#xff0c;每个知识点的修正和深入主要参考…

Prometheus 服务端与客户端

服务端安装配置 1&#xff09;下载服务端&#xff1a; wget https://github.com/prometheus/prometheus/releases/download/v2.43.0-rc.0/prometheus-2.43.0-rc.0.linux-amd64.tar.gztar zxvf prometheus-2.43.0-rc.0.linux-amd64.tar.gz#解压 tar -xvf prometheus-2.32.1.li…

iOS开发-启动页广告实现

iOS开发-启动页广告实现 启动页广告实现是一个非常常见的广告展示模式。 就是在启动时候显示广告&#xff0c;之后点击跳转到广告页面或者其他APP。 一、实现启动页广告 启动页广告控件实现&#xff0c;将View放置在keyWindow上&#xff0c;显示广告图片&#xff0c;点击广告…

https://app.hackthebox.com/machines/Sau

https://app.hackthebox.com/machines/Sau https://app.hackthebox.com/machines/Sau1.info collecting └─$ nmap -A 10.10.11.224 -T4 Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-30 15:36 HKT Nmap scan report for 10.10.11.224 (10.10.11.224) Host is up (…

Arrays(数组)工具类

java.util.Arrays 是一个与数组相关的工具类&#xff0c;里面提供了大量静态方法&#xff0c;用来实现数组常见的操作。 Arrays.toString ( 数组名 )将参数数组变成字符串&#xff08;按照默认格式&#xff1a;[10, 20, 30]&#xff09;Array.sort ( 数组名 ) 按照默认升序&…