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

文章目录

  • 映射关系多对一
    • 映射关系-官方文档
    • 映射关系多对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();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux驱动定时器实现按键按下打印字符

#include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/interrupt.h>struct device_node *dev; unsigned int irqno; //中断处理函数 irqreturn_t myirq_handler(int irq,void *…

51单片机--红外遥控

文章目录 红外遥控的介绍硬件电路NEC编码外部中断红外遥控实例代码 红外遥控的介绍 红外遥控是一种无线、非接触控制技术&#xff0c;通过使用红外线来传送控制信号。它具有抗干扰能力强、信息传输可靠、功耗低、成本低、易实现等显著优点&#xff0c;因此被广泛应用于各种电子…

IDEA Debug小技巧 添加减少所查看变量、查看不同线程

问题 IDEA的Debug肯定都用过。它下面显示的变量&#xff0c;有什么门道&#xff1f;可以增加变量、查看线程吗&#xff1f; 答案是&#xff1a;可以。 演示代码 代码如下&#xff1a; package cn.itcast.attempt.threadAttempt.attempt2;public class Test {public static …

27岁到来之际,我在阿里实现了年薪30W+的小目标

毕业快 5 年了&#xff0c;每当和人聊起自己的职场飞升之路&#xff0c;都不由得感激当初果断逃离舒适圈的自己。出身一所非 211、985 院校&#xff0c;毕业后入职了一家小型互联网公司&#xff0c;当着普普通通的初级测试工程师&#xff0c;工作期间虽然也时常遇到挑战&#x…

HTTP之Session、Cookie 与 Application

目录 简介cookiecookie生命周期 sessionsession生命周期 HTTP cookies示例application 简介 cookie、seesion、application三个都会缓存我们用户状态的数据&#xff0c;使得我们在浏览器访问网站时可以更快速的获取到信息。 主要原因在于HTTP协议是无状态的&#xff0c;我们每…

计算机视觉(四)神经网络与典型的机器学习步骤

文章目录 神经网络生物神经元人工神经元激活函数导数 人工神经网络“层”的通俗理解 前馈神经网络Delta学习规则前馈神经网络的目标函数梯度下降输出层权重改变量 误差方向传播算法误差传播迭代公式简单的BP算例随机梯度下降&#xff08;SGD&#xff09;Mini-batch Gradient De…

搭建工程化项目

搭建工程化项目 首先创建一个 study 空文件夹&#xff0c;并且把它拖到 VS Code 里面。 在 VS Code 中打开终端&#xff0c;快捷键 ctrl ~ 在命令行中输入 npm init&#xff0c;在接下来所有选项中全部按 “回车” 采用默认即可。 初始化完毕后&#xff0c;在项目根目录下会出…

TypeScript 【type】关键字的进阶使用方式

导语&#xff1a; 在前面章节中&#xff0c;我们了解到 TS 中 type 这个关键字&#xff0c;常常被用作于&#xff0c;定义 类型别名&#xff0c;用来简化或复用复杂联合类型的时候使用。同时也了解到 为对象定义约束接口类型 的时候所使用的是 Interfaces。 其实对于前面&#…

C# Blazor 学习笔记(4):blazor代码分离

文章目录 前言代码分离 前言 Blazor可以支持在razor文件里面添加cs代码&#xff0c;但是代码一旦复杂了之后就会变得特别的麻烦。但是VS提供了代码分组的功能。 分离前 分离后 代码分离 我们直接右键razor组件是不能直接添加cs代码部分的 注意新建类的类名是xxx.razor…

软考中级信息安全工程师2023下半年报名时间及报名入口官网

软考中级信息安全工程师2023下半年考试时间&#xff1a; 2023年下半年软考中级信息安全工程师的考试时间为11月4日、5日。考试时间在全国各地一致&#xff0c;建议考生提前备考。共分两科&#xff0c;第一科基础知识考试具体时间为9:00-11:30&#xff1b;第二科应用技术考试具…

transformers里的AutoTokenizer之返回值token_type_ids(二)

在很多案例中&#xff0c;AutoTokenizer会返回token_type_ids这个结果&#xff1a; token_type_ids的解释&#xff1a; 对于两个句子对来说&#xff0c;上一句都标识为0&#xff0c;下一句都标识为1。

Hadoop优化

1.Datanode管理多块数据盘 1.理解 其实就是扩展Datanode空间,之前一个盘,现在加一个盘或者多个盘, 2.优点: 1.提高容错(避免硬盘损坏全部数据丢失)2.实现数据分离模式存储(框架本体与数据分离,集群出现问题数据可进行单独恢复,这样也是提高容错) 3.配置&#xff08;临时挂…

[PyTorch][chapter 45][RNN_2]

目录&#xff1a; RNN 问题 RNN 时序链问题 RNN 词组预测的例子 RNN简洁实现 一 RNN 问题 RNN 主要有两个问题&#xff0c;梯度弥散和梯度爆炸 1.1 损失函数 梯度 其中&#xff1a; 则 1.1 梯度爆炸&#xff08;Gradient Exploding&#xff09; 上面矩阵进行连乘后…

uniapp使用getStorage对属性赋值无效

1正常set(get)storage都是可以正常使用的 2.但对属性进行赋值的时候&#xff0c;却发现this.name并没有发生变化 3. 在里面打印this发现&#xff0c;在set*getStorage中并不能拿到this. 4.优化代码 这样就可以给this.name成功赋值

重学C++系列之STL库

一、什么是STL库 STL是“Standard Template Library”的缩写&#xff0c;中文翻译为“标准模板库”。CSTL是一套功能强大的C模板类&#xff0c;提供了通用的模板类和函数&#xff0c;这些模板类和函数可以实现多种流行和常用的算法和数据结构&#xff0c;如字符串操作、链表、队…

如何为新一代可持续应用设计电机编码器

从定速电机转向提供位置和电流反馈的变速电机&#xff0c;不仅可以实现工艺改进&#xff0c;还能节省大量能源。本文介绍了电机编码器&#xff08;位置和速度&#xff09;、器件类型和技术以及应用案例。此外还解答了一些关键问题&#xff0c;例如对特定系统最重要的编码器性能…

Prometheus 的应用服务发现及黑河部署等

目录 promtool检查语法 部署Prometheus Server 检查语法是否规范 部署node-exporter 部署Consul 直接请求API进行服务注册 使用register命令注册服务&#xff08;建议使用&#xff09; 单个和多个注册&#xff0c;多个后面多加了s 在Prometheus上做consul的服务发现 部署…

ChatGPT漫谈(三)

AIGC(AI Generated Content)指的是使用人工智能技术生成的内容,包括文字、图像、视频等多种形式。通过机器学习、深度学习等技术,AI系统可以学习和模仿人类的创作风格和思维模式,自动生成大量高质量的内容。AIGC被视为继用户生成内容(UGC)和专业生成内容(PGC)之后的下…

【无标题】JSP--Java的服务器页面

jsp是什么&#xff1f; jsp的全称是Java server pages,翻译过来就是java的服务器页面。 jsp有什么作用&#xff1f; jsp的主要作用是代替Servlet程序回传html页面的数据&#xff0c;因为Servlet程序回传html页面数据是一件非常繁琐的事情&#xff0c;开发成本和维护成本都非常高…