快速了解MyBatis---映射关系多对一

news2024/11/15 20:47:12

文章目录

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

映射关系多对一

映射关系-官方文档

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

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

基本介绍

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

注意细节

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

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

映射方式

方式1:通过配置XxxMapper.xml 实现多对1

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

配置Mapper.xml 方式-应用实例

需求说明: 实现级联查询,通过user 的id 可以查询到用户信息,并可以查询到关联的pet信息,

​ 反过来,通过Pet 的id 可以查询到Pet 的信息,并且可以级联查询到它的主人User对象信息。

  1. 创建mybatis_user 和mybatis_pet 表
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;

image-20230731145051413

  1. 创建src\main\java\com\nlc\entity\Pet.java
public class Pet {
    private Integer id;
    private String nickname;
    //一个pet对应一个主人 User对象
    private User user;

    public Integer getId() {
        return id;
    }

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

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

创建src\main\java\com\nlc\entity\User.java

public class User {
    private Integer id;
    private String name;
    //因为一个user可以养多个宠物,mybatis 使用集合List<Pet>体现这个关系
    private List<Pet> pets;

    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 List<Pet> getPets() {
        return pets;
    }

    public void setPets(List<Pet> pets) {
        this.pets = pets;
    }

    //这toString会带来麻烦=>会造成StackOverFlow
    //@Override
    //public String toString() {
    //    return "User{" +
    //            "id=" + id +
    //            ", name='" + name + '\'' +
    //            ", pets=" + pets +
    //            '}';
    //}
}
  1. 创建PetMapper.java

    public interface PetMapper {
        //通过User的id来获取pet对象,可能有多个,因此使用List接收
        public List<Pet> getPetByUserId(Integer userId);
        
        //通过pet的id获取Pet对象, 同时会查询到pet对象关联的user对象
        public Pet getPetById(Integer id);
    }
    

    创建UserMapper.java

public interface UserMapper {

    //通过id获取User对象
    public User getUserById(Integer id);

}
  1. 创建UserMapper.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 nameNlcace="com.nlc.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.nlc.mapper.PetMapper.getPetByUserId"/>
        </resultMap>
        <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
            SELECT * FROM `mybatis_user` WHERE `id` = #{id}
        </select>
    
    </mapper>
    
  2. 创建PetMapper.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 nameNlcace="com.nlc.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.nlc.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. 创建PetMapperTest.java 完成测试

    public class PetMapperTest {
        //属性
        private SqlSession sqlSession;
        private PetMapper petMapper;
    
        //初始化
        @Before
        public void init() {
            //获取到sqlSession
            sqlSession = MyBatisUtils.getSqlSession();
            petMapper = sqlSession.getMapper(PetMapper.class);
        }
    
        @Test
        public void getPetByUserId() {
            List<Pet> pets = petMapper.getPetByUserId(2);
            for (Pet pet : pets) {
                System.out.println("pet信息-" + pet.getId() + "-" + pet.getNickname());
                User user = pet.getUser();
                System.out.println("user信息 name-" + user.getName());
            }
            if(sqlSession != null) {
                sqlSession.close();
            }
        }
        
        @Test
        public void getPetById() {
            Pet pet = petMapper.getPetById(2);
            System.out.println("pet信息-" + pet.getId() + "-" + pet.getNickname());
            User user = pet.getUser();
            System.out.println("user信息-" + user.getId() + "-" + user.getName());
            if(sqlSession != null) {
                sqlSession.close();
            }
        }
    }
    
  2. 创建UserMapperTest.java 完成测试

    public class UserMapperTest {
    
        //属性
        private SqlSession sqlSession;
        private UserMapper userMapper;
    
        //初始化
        @Before
        public void init() {
            //获取到sqlSession
            sqlSession = MyBatisUtils.getSqlSession();
            userMapper = sqlSession.getMapper(UserMapper.class);
        }
    
        @Test
        public void getUserById() {
            User user = userMapper.getUserById(2);
    
            System.out.println("user信息-" + user.getId() + "-" + user.getName());
    
            List<Pet> pets = user.getPets();
            for (Pet pet : pets) {
                System.out.println("养的宠物信息-" + pet.getId() + "-" + pet.getNickname());
            }
            if(sqlSession != null) {
                sqlSession.close();
            }
        }
    }
    

注解实现多对1 映射-应用实例

需求说明: 通过注解的方式来实现下面的多对1 的映射关系,实现级联查询,

完成前面完成的任务,通过User–>Pet 也可Pet->User , 在实际开发中推荐使用配置方式来做

  1. 创建UserMapperAnnotation.java
// UserMapperAnnotation:以注解的方式来配置多对一
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.nlc.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.nlc.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    public User getUserById(Integer id);
}
  1. 创建PetMapperAnnotation.java
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.nlc.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.nlc.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. 创建UserMapperAnnotationTest.java 完成测试
public class UserMapperAnnotationTest {
    //属性
    private SqlSession sqlSession;
    private UserMapperAnnotation userMapperAnnotation;

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

    @Test
    public void getUserById() {

        User user = userMapperAnnotation.getUserById(2);
        System.out.println("user信息-" + user.getId() + "-" + user.getName());

        List<Pet> pets = user.getPets();
        for (Pet pet : pets) {
            System.out.println("宠物信息-" + pet.getId() + "-" + pet.getNickname());
        }

        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}
  1. 创建PetMapperAnnotationTest.java 完成测试
public class PetMapperAnnotationTest {
    //属性
    private SqlSession sqlSession;
    private PetMapperAnnotation petMapperAnnotation;

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

    @Test
    public void getPetByUserId() {

        List<Pet> pets = petMapperAnnotation.getPetByUserId(1);
        for (Pet pet : pets) {
            System.out.println("宠物信息-" + pet.getId() + "-" + pet.getNickname());
        }

        if(sqlSession != null) {
            sqlSession.close();
        }
    }

    @Test
    public void getPetById() {

        Pet pet = petMapperAnnotation.getPetById(1);
        System.out.println("pet信息-" + pet.getId() + "-" +pet.getNickname());
        User user = pet.getUser();
        System.out.println("user信息-" + user.getId() + "-" + user.getName());
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}

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

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

相关文章

(树) 剑指 Offer 32 - I. 从上到下打印二叉树 ——【Leetcode每日一题】

❓剑指 Offer 32 - I. 从上到下打印二叉树 难度&#xff1a;中等 从上到下打印出二叉树的每个节点&#xff0c;同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3/ \9 20/ \15 7返回&#xff1a; [3,9,20,15,7]提示&#xff1a; 节…

软件测试——Postman Script脚本功能

Postman作为软件测试里一款非常流行的调试工具&#xff0c;给我们提供了一个执行JavaScript脚本的环境&#xff0c;所以我们可以使用js语言编写脚本来解决一些接口自动化的问题&#xff0c;比如接口依赖、接口断言等等。Postman有Pre-RequestScript和Tests两个编写js脚本的模块…

【LeetCode】最小路径和

最小路径和 题目描述算法流程编程代码 链接: 最小路径和 题目描述 算法流程 编程代码 class Solution { public:int minPathSum(vector<vector<int>>& grid) {int m grid.size();int n grid[0].size();vector<vector<int>> dp(m1,vector<in…

html5播放器视频切换和连续播放的实例

当前播放器实例可以使用changeVid接口切换正在播放的视频。当有多个视频&#xff0c;在上一个视频播放完毕时&#xff0c;自动播放下一个视频时也可采用该处理方式。 const option {vid: 88083abbf5bcf1356e05d39666be527a_8,//autoplay: true,//playsafe: , //PC端播放加密视…

ipad必须要配原装的电容笔吗?ipad可以用的手写笔

众所周知&#xff0c;苹果平板电脑的价格很贵&#xff0c;但只要你有充足的预算&#xff0c;是可以选择入手的。另外&#xff0c;iPad搭配上电容笔不但适用于专业画图&#xff0c;也适用于写字作笔记。苹果原装的电容笔&#xff0c;功能强大&#xff0c;但是价格昂贵&#xff0…

记录一个可支持 style 属性 HtmlTextView 控件

大家都知道可通过原生API Html.fromHtml(html) 在 TextView 上显示 html 文本&#xff0c;但显示效果有限。 对于复杂效果就不行了&#xff0c;费了点时间找了一些库验证&#xff0c;最终找到一个合适的&#xff0c;在此记录一下。 支持内容挺丰富的&#xff0c;包含很多 htm…

Mac查看系统状态

syatem profiler mac系统中提供了system profiler来查看系统的详细信息&#xff0c;包括硬件、网络以及安装的软件 Console 显示了系统上的日志文件信息&#xff0c;有助于诊断问题 Activity Monitor 可以提供正在运行的系统的相关信息 https://zhhll.icu/2021/Mac/查看系统…

学习记录——Octave Convolution、LSK

Octave Convolution 2019 ICCV 自然世界中的图像存在高低频&#xff0c;卷积层的输出特征图以及输入通道&#xff0c;也都存在高、低频分量。 低频分量支撑的是整体轮廓&#xff0c;高频分量则关注细节&#xff0c;显然&#xff0c;低频分量是存在冗余的&#xff0c;在编码过程…

LLM微调 | Prefix-Tuning, Prompt-Tuning, P-tuning, P-tuning-v2

&#x1f525; 下面我只是分析讲解下这些方法的原理以及具体代码是怎么实现的&#xff0c;不对效果进行评价&#xff0c;毕竟不同任务不同数据集效果差别还是挺大的。 文章目录 0、hard prompt & soft prompt区别1、Prefix-Tuning2、Prompt-Tuning3、P-tuning4、P-tuning-v…

【C++】stack | queue | priority_queue的模拟实现

stack&queue的模拟实现 stack 与 queue 作为容器适配器&#xff0c;都默认选择了 deque 作为其底层容器。 #pragma once #include <deque> using namespace std;namespace zs {template<class T, class Container deque<T>>class stack{public:void p…

【Java基础教程】(四十四)IO篇 · 上:File类、字节流与字符流,分析字节输出流、字节输入流、字符输出流和字符输入流的区别~

Java基础教程之IO操作 上 &#x1f539;本节学习目标1️⃣ 文件操作类&#xff1a;File2️⃣ 字节流与字符流2.1 字节输出流&#xff1a;OutputStream2.2 字节输入流&#xff1a;InputStream2.3 字符输出流&#xff1a;Writer2.4 字符输入流&#xff1a;Reader2.5 字节流与字符…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(15)-Fiddler弱网测试,知否知否,应是必知必会

1.简介 现在这个时代已经属于流量时代&#xff0c;用户对于App或者小程序之类的操作界面的数据和交互的要求也越来越高。对于测试人员弱网测试也是需要考验自己专业技术能力的一种技能。一个合格的测试人员&#xff0c;需要额外关注的场景就远不止断网、网络故障等情况了。还要…

grid map学习笔记2之grid map的一些常规定义和功能包说明

文章目录 0 引言1 常规定义1.1 单层grid map1.2 多层grid map1.3 迭代器类别1.4 移动grid map的位置 2 功能包2.1 grid_map_rviz_plugin2.2 grid_map_sdf2.3 grid_map_visualization2.3.1 订阅的主题2.3.2 发布的主题 2.4 grid_map_filters 0 引言 grid map学习笔记1已成功在U…

数据结构:复习笔记

目录 前言1. 数据结构绪论1.1 数据结构的概念及分类1.1.1 知识点提要1.1.2 选择判断与简答归纳1.1.3 算法编程题 1.2 算法设计与算法分析1.2.1 知识点提要1.2.2 选择判断与简答归纳1.2.3 算法编程题 2. 线性表2.1 线性表的概念2.1.1 知识点提要2.1.2 选择判断与简答归纳2.1.3 算…

【yolov8+人/车流量统计】yolov8案例的追踪case,业务化可以变成计数

文章目录 前言修改点PreprocessInference 另一种方法&#xff0c;work了。一个难点&#xff0c;它走到了这里 业务化修改总结 前言 之前写个yolov8的一个试用版&#xff0c;【深度学习】Yolov8追踪从0到1, 这要是做计数啥的,简单的一批&#xff0c;一套工程化的代码&#xff0…

abp vnext指定版本下载

在本地环境没有达到最新的开发环境时可能无法下载abp vnext的最新版本&#xff0c;我们应该指定下载符合本地开发环境的abp版本&#xff0c;下面一起看一下&#xff1a; 首先查看本地电脑的开发环境版本&#xff1a; cmd dotnet --version dotnet --list-version ABP VNext和…

师从美国四院院士|遗传学老师赴哥伦比亚大学访问交流

H老师为省公派访学&#xff0c;目标为美国知名高校&#xff0c;最终我们获得了哥伦比亚大学的邀请函&#xff0c;导师是美国科学院院士、美国艺术与科学院院士、美国微生物学院院士、美国科学促进会会士等四个学会的院士&#xff0c;堪称学术界的超级大牛。 H老师背景&#xff…

Spark性能调优指南来了!

1、什么是Spark Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 Spark Core&#xff1a;实现了Spark的基本功能&#xff0c;包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core中还包含了对弹性分布式数据集(Resilient Distributed Dat…

【Ansible 的脚本 --- playbook 剧本】

目录 一、playbook 剧本介绍二、示例1、运行playbook2、定义、引用变量 三、使用playbook部署lnmp集群 一、playbook 剧本介绍 playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在…

从多个基础CMS中学习代码审计

代码审计 概念 什么是代码审计&#xff1f; 代码审计是在一个编程中对源代码旨在发现错误、安全漏洞或违反编程约定的项目。 说人话就是找它这些代码中可能存在问题的地方&#xff0c;然后看它是否真的存在漏洞。(博主小白&#xff0c;可能存在问题&#xff0c;请见谅) 分类…