Mybatis进阶(映射关系多对一 )

文章目录

    • 1.需求分析
    • 2.应用实例(xml配置)
        • 1.数据表设计
        • 2.entity设计(不要使用toString会栈溢出)
          • 1.Pet.java
          • 2.User.java
        • 3.编写Mapper
          • 1.PetMapper.java
          • 2.UserMapper.java
        • 4.编写Mapper.xml
          • 1.UserMapper.xml
          • 2.PetMapper.xml
        • 5.测试UserMapperTest.java
        • 6.resultMap复用实现PetMapper.java的getPetById方法
          • 1.修改PetMapper.xml添加实现类
          • 2.测试
    • 3.应用实例(注解方式)
        • 1.UserMapperAnnotation.java
        • 2.PetMapperAnnotation.java
    • 4.课后练习(一对多)
        • 1.数据表设计
        • 2.entity设计(不要使用toString会栈溢出)
          • 1.Dept.java
          • 2.Emp.java
        • 3.编写Mapper
          • 1.DeptMapper.java
          • 2.EmpMapper.java
        • 4.编写Mapper.xml
          • 1.DeptMapper.xml
          • 2.EmpMapper.xml
        • 5.测试DeptMapperTest.java
    • 5.MyBatis映射关系总结
        • 1.一对一
          • 1.表设计
          • 2.entity设计
          • 3.Mapper设计
        • 2.一对多(多对一)
          • 1.表设计
          • 2.entity设计
          • 3.Mapper设计
          • 4.最简化的理解

1.需求分析

image-20240306141119151

2.应用实例(xml配置)

1.数据表设计
CREATE TABLE mybatis_user(
	id INT PRIMARY KEY auto_increment,
	name VARCHAR(32) NOT NULL DEFAULT ''
);

CREATE TABLE mybatis_pet(
	id INT PRIMARY KEY auto_increment,
	nickname VARCHAR(32) NOT NULL DEFAULT '',
	user_id INT
);

INSERT INTO mybatis_user VALUES(NULL, '宋江'), (NULL, '张飞');

INSERT INTO mybatis_pet VALUES(NULL, '黑背', 1), (NULL, '小哈', 1);

INSERT INTO mybatis_pet VALUES(NULL, '波斯猫', 2), (NULL, '贵妃猫', 2);

SELECT * FROM mybatis_user;

SELECT * FROM mybatis_pet;
2.entity设计(不要使用toString会栈溢出)
1.Pet.java
package com.sun.entity;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Pet {
    private Integer id;
    private String nickname;
    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;
    }

}

2.User.java
package com.sun.entity;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class User {
    private Integer id;
    private String name;
    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;
    }

}

3.编写Mapper
1.PetMapper.java
package com.sun.mapper;

import com.sun.entity.Pet;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface PetMapper {
    //根据用户id获取所有宠物
    public List<Pet> getPetByUserId(Integer userId);
    //根据pet的id获取对象
    public Pet getPetById(Integer id);
}

2.UserMapper.java
package com.sun.mapper;

import com.sun.entity.User;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface UserMapper {
    //根据id获取当前用户
    public User getUserById(Integer id);
}

4.编写Mapper.xml
1.UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sun.mapper.UserMapper">
    <resultMap id="getUserByIdresultMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--如果是一个集合类型的属性需要使用collection标签,并需要指定ofType属性来决定返回集合中存储的类型-->
        <collection property="pets" column="id" select="com.sun.mapper.PetMapper.getPetByUserId" ofType="Pet"/>
    </resultMap>
    <!--public User getUserById(Integer id);-->
    <select id="getUserById" parameterType="Integer" resultMap="getUserByIdresultMap">
        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"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sun.mapper.PetMapper">

    <!--public List<Pet> getPetByUserId(Integer userId);-->
    <resultMap id="getPetByUserId_resultMap" type="Pet">
        <id property="id" column="id"/>
        <result property="nickname" column="nickname"/>
        <association property="user" column="user_id" select="com.sun.mapper.UserMapper.getUserById"/>
    </resultMap>
    <select id="getPetByUserId" parameterType="Integer" resultMap="getPetByUserId_resultMap">
        SELECT * FROM mybatis_pet WHERE user_id = #{userId}
    </select>
</mapper>
5.测试UserMapperTest.java
import com.sun.entity.Pet;
import com.sun.entity.User;
import com.sun.mapper.PetMapper;
import com.sun.mapper.UserMapper;
import com.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class UserMapperTest {
    private SqlSession sqlSession; //相当于连接
    private UserMapper userMapper;

    //编写方法完成初始化
    @Before //标注了Before之后表示了在执行目标测试方法前会执行该方法
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        //获取到MonsterMapper对象
        userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper.getClass());
    }

    @Test
    public void getUserById() {
        User user = userMapper.getUserById(1);
        System.out.println(user.getName() + "-" + user.getId());
        List<Pet> pets = user.getPets();
        for (Pet pet : pets) {
            System.out.println(pet.getId() + "-" + pet.getNickname() + "-" + pet.getUser());
        }
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

6.resultMap复用实现PetMapper.java的getPetById方法
1.修改PetMapper.xml添加实现类
    <!--public Pet getPetById(Integer id);-->
    <select id="getPetById" parameterType="Integer" resultMap="getPetByUserId_resultMap">
        SELECT * FROM mybatis_pet WHERE id = #{id}
    </select>
2.测试
    @Test
    public void getPetById() {
        Pet petById = petMapper.getPetById(1);
        System.out.println(petById.getId() + " " + petById.getNickname() + " " + petById.getUser());
    }

image-20240306171019487

3.应用实例(注解方式)

1.UserMapperAnnotation.java
package com.sun.mapper;

import com.sun.entity.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface UserMapperAnnotation {
    //根据id获取当前用户
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "name", column = "name"),
            //这里根据查询到的id调用pet的方法返回一个Pet对象的列表,并且是多条记录使用many
            @Result(property = "pets", column = "id", many = @Many(select = "com.sun.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    @Select("SELECT * FROM mybatis_user WHERE id = #{id}")
    public User getUserById(Integer id);
}

2.PetMapperAnnotation.java
package com.sun.mapper;

import com.sun.entity.Pet;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface PetMapperAnnotation {

    @Results(id = "getPetByUserIdResultMap",value = {
            //这里的id表示这个resultMap的id,可以被复用
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "nickname", column = "nickname"),
            //根据user_id来返回一个User对象,返回一个对象使用one
            @Result(property = "user", column = "user_id", one = @One(select = "com.sun.mapper.UserMapperAnnotation.getUserById"))
    })
    @Select("SELECT * FROM mybatis_pet WHERE user_id = #{userId}")
    public List<Pet> getPetByUserId(Integer userId);


    //根据pet的id获取对象
    //这里直接使用resultMap注解来复用上面的getPetByUserIdResultMap
    @ResultMap("getPetByUserIdResultMap")
    @Select("SELECT * FROM mybatis_pet WHERE id = #{id}")
    public Pet getPetById(Integer id);
}

4.课后练习(一对多)

image-20240306185715900

1.数据表设计
CREATE TABLE dept(
id INT PRIMARY KEY auto_increment,
name VARCHAR(32) NOT NULL DEFAULT ''
)

-- 多的一方设置外键
CREATE TABLE emp(
id INT PRIMARY KEY auto_increment,
name VARCHAR(32) NOT NULL DEFAULT '',
dept_no INT NOT NULL DEFAULT 0 
)

INSERT INTO dept VALUES(NULL, '财务部');
INSERT INTO dept VALUES(NULL, '外交部');

INSERT into emp VALUES(NUll, '李白1', 1);
INSERT into emp VALUES(NUll, '孙悟空1', 2);
INSERT into emp VALUES(NUll, '李白2', 1);
INSERT into emp VALUES(NUll, '孙悟空2', 2);
2.entity设计(不要使用toString会栈溢出)
1.Dept.java
package com.sun.entity;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Dept {
    private Integer id;
    private String name;

    //一:可级联查询多个Emp
    private List<Emp> emps;

    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<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }
}

2.Emp.java
package com.sun.entity;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Emp {
    private Integer id;
    private String name;

    //多:可级联查询单个Dept
    private Dept dept;

    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 Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }
}

3.编写Mapper
1.DeptMapper.java
package com.sun.mapper;

import com.sun.entity.Dept;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface DeptMapper {
    //根据id查询部门,级联查询该部门的多个雇员
    public Dept findById(Integer id);

}

2.EmpMapper.java
package com.sun.mapper;

import com.sun.entity.Emp;

import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface EmpMapper {
    //根据部门id查询多个雇员,并级联查询一个部门
    public List<Emp> findByDeptId(Integer dept_id);
}

4.编写Mapper.xml
1.DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定该xml文件和哪个接口对应-->
<mapper namespace="com.sun.mapper.DeptMapper">
    <!--public Dept findById(Integer id);-->
    <resultMap id="findByIdMap" type="Dept">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="emps" column="id" ofType="Emp" select="com.sun.mapper.EmpMapper.findByDeptId"/>
    </resultMap>
    <select id="findById" parameterType="Integer" resultMap="findByIdMap">
        SELECT * FROM dept WHERE id = #{id}
    </select>
</mapper>

2.EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定该xml文件和哪个接口对应-->
<mapper namespace="com.sun.mapper.EmpMapper">
    <!--public List<Emp> findByDeptId(Integer dept_id);-->
    <resultMap id="findByDeptIdMap" type="Emp">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="dept" column="dept_no" select="com.sun.mapper.DeptMapper.findById"/>
    </resultMap>
    <select id="findByDeptId" parameterType="Integer" resultMap="findByDeptIdMap">
        SELECT * FROM emp WHERE dept_no = #{dept_id}
    </select>
</mapper>

5.测试DeptMapperTest.java
import com.sun.entity.Dept;
import com.sun.mapper.DeptMapper;
import com.sun.mapper.HusbandMapper;
import com.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class DeptMapperTest {
    private SqlSession sqlSession; //相当于连接
    private DeptMapper deptMapper;

    //编写方法完成初始化
    @Before //标注了Before之后表示了在执行目标测试方法前会执行该方法
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        //获取到MonsterMapper对象
        deptMapper = sqlSession.getMapper(DeptMapper.class);
        System.out.println(deptMapper.getClass());
    }

    @Test
    public void findById() {
        Dept byId = deptMapper.findById(1);
        System.out.println(byId.getId() +" " + byId.getName());
    }
}

image-20240306201131236

5.MyBatis映射关系总结

1.一对一
1.表设计
  • 有外键的是从表,被指向的是主表
  • 设置一个有外键的从表指向一个主表(一般指向主键)
2.entity设计
  • 在表中有外键的一方将外键的字段部分替换为指向的主表的entity对象
3.Mapper设计
  • 查询有外键的一方的基本信息和级联的另一方的信息
  • 注意:如果想要双向映射,不需要再加一个外键,只需要在另一个entity实体类中加上一个entity对象即可
2.一对多(多对一)
1.表设计
  • 多的一方有外键
2.entity设计
  • 一的一方
    • 基本属性
    • 一个集合,类型为多的一方
  • 多的一方
    • 基本属性
    • 一个对象,类型为一的一方
3.Mapper设计
  • 一方查询
    • 查询一方的基本信息
    • 级联查询多方的信息
  • 多方查询
    • 查询多方的基本信息
    • 级联查询单方的信息
4.最简化的理解
  • 确定一方与多方关联的列名,简述为关联列名
  • 一方查询基本信息,使用关联列名级联查询多方信息
  • 多方查询基本信息,使用关联列名查询一方信息

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

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

相关文章

OPPO A72/A55/K7X/A53真我Q3S等手机ROOT刷机后广电卡没信号不读卡解决办法

目前运营商除了移动联通电信以外&#xff0c;还存在1个中国广电&#xff0c;广电属于第四大运营商&#xff0c;由于广电起步较晚&#xff0c;对于手机频段要求也自然不一样&#xff0c;导致目前市面上部分手机出厂没有信号或者不读卡等问题&#xff0c;特别在手机被用户自行刷机…

如何快速的追加文章的内容(在不知道内容的情况下)

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 1、打开工具&#xff0c;切换到文章模块下&#xff0c;快捷键&#xff1a;Ctrl1 2、新建一个文章做演示&#xff0c;001 3、添加一个内容&#xff0c;就随…

蚂蚁面试:Springcloud核心组件的底层原理,你知道多少?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团、蚂蚁、得物的面试资格&#xff0c;遇到很多很重要的相关面试题&#xff1a; 说说&#xff1a;蚂蚁面试&#xff1…

【Java】HOT100 贪心算法

目录 理论基础 一、简单贪心 LeetCode455&#xff1a;分发饼干 二、中等贪心 2.1 序列问题 LeetCode376&#xff1a;摆动序列 2.2 贪心股票问题 LeetCode121&#xff1a;买卖股票的最佳时机 LeetCode121&#xff1a;买卖股票的最佳时机ii 2.3 两个维度权衡问题 LeetCode135&…

【06016传感器原理与应用】第5章 气敏传感器 期末复习自考复习

第5章 气敏传感器 能够把气体信息变成电信号的装置。 一、学习目的与要求 通过本章的学习&#xff0c;熟悉并掌握气体传感器的工作原理和硬件组成结构。熟练掌握几种电阻式尤其TiO2、SnO2气敏传感器、非电阻式气敏传感器、固体电解质传感器、接触燃烧式气敏传感器的基本原理…

karpathy makemore 3

1 Introduction 这一章&#xff0c;karpathy通过分析参数初始化对模型的收敛的影响作为一个引子&#xff0c;让我们看到神经网络这一个复杂的系统&#xff0c;对grad非常敏感&#xff0c;以及有一些技巧可以解决grad敏感的问题。 2 准备工作 2.1 dataloader import torch b…

DS:顺序表、单链表的相关OJ题训练

欢迎各位来到 Harper.Lee 的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦&#xff01; 在DS&#xff1a;单链表的实现 和 DS&#xff1a;顺序表的实现这两篇文章中&#xff0c;我详细介绍了顺序表和单链表的…

PAT (Advanced Level) - 1047 Student List for Course

模拟 #include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std;const int N 40010, M 2510;int n, k; string name[N]; vector<int> list[M];int main() {scanf("%d%d", &n, &…

万万没想到,延缓帕金森病进展的“玄机”竟然就在腿上?【北京仁爱堂】

帕金森病患者的腿部变化&#xff0c;其实可以反应出很多问题。例如行走的变化问题、步态的异常等问题&#xff0c;可以反应病情轻重程度。而通过保持腿部肌肉活动的状态&#xff0c;也可以使帕金森病的症状得到一定的缓解&#xff0c;甚至有助于防止病情恶化。 帕金森病腿部变…

2024年五一数学建模竞赛C题论文首发

基于随机森林的煤矿深部开采冲击地压危险预测 摘要 煤炭作为中国重要的能源和工业原料&#xff0c;其开采活动对国家经济的稳定与发展起着至关重要的作用。本文将使用题目给出的数据探索更为高效的数据分析方法和更先进的监测设备&#xff0c;以提高预警系统的准确性和可靠性…

Photoshop前言

Photoshop前言 分辨率图像格式工具界面组件 分辨率 分辨率是指单位长度内包含的像素点的数量&#xff0c;其单位通常为像素/英寸&#xff08;ppi&#xff09;&#xff0c;300ppi表示每英寸包含300个像素点。对于1英寸1英寸大小的图像&#xff0c;若分辨率为72ppi&#xff0c;则…

基于Pytorch深度学习——多层感知机

本文章来源于对李沐动手深度学习代码以及原理的理解&#xff0c;并且由于李沐老师的代码能力很强&#xff0c;以及视频中讲解代码的部分较少&#xff0c;所以这里将代码进行尽量逐行详细解释 并且由于pytorch的语法有些小伙伴可能并不熟悉&#xff0c;所以我们会采用逐行解释小…

Visio 2021 (64bit)安装教程

Visio 2021 (64bit)安装教程 ​ 通知公告 Visio 2021 (64位) 是一款流程图和图表设计工具,主要用于创建和编辑各种类型的图表和图形。它提供了一个直观的界面和丰富的功能,可以帮助用户快速绘制专业的流程图、组织结构图、网络图、平面图、数据库模型等。 具体来说,Visio 20…

Go 语言数组

Go 语言提供了数组类型的数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列&#xff0c;这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。 相对于去声明 number0, number1, ..., number99 的变量&#xff0c;使用数组形式 numbers[0], num…

Spring Cloud——Circuit Breaker上篇

Spring Cloud——Circuit Breaker上篇 一、分布式系统面临的问题1.服务雪崩2.禁止服务雪崩故障 二、Circuit Breaker三、resilience4j——服务熔断和降级1.理论知识2.常用配置3.案例实战&#xff08;1&#xff09;COUNT_BASED&#xff08;计数的滑动窗口&#xff09;&#xff0…

Spring Cloud——OpenFeign

Spring Cloud——OpenFeign 一、OpenFeign能干嘛二、OpenFeign的基本使用三、Feign的高级特性1.OpenFeign超时控制2.OpenFeign重试机制3.OpenFeign之性能优化HttpClient54.OpenFeign请求和响应压缩5.OpenFeign之Feign日志打印 四、参考 OpenFeign是一个声明式的Web服务客户端。…

Android --- 消息机制与异步任务

在Android中&#xff0c;只有在UIThread(主线程)中才能直接更新界面&#xff0c; 在Android中&#xff0c;长时间的工作联网都需要在workThread(分线程)中执行 在分线程中获取服务器数据后&#xff0c;需要立即到主线程中去更新UI来显示数据&#xff0c; 所以&#xff0c;如…

程序员的五大方法论

前言&#xff1a; 最近看了一篇总结程序员学习&#xff0c;晋升方法的文章&#xff0c;颇有感想&#xff0c;决定分享给大家&#xff0c;原文地址&#xff1a;给程序员的5条学习方法论 (qq.com)https://mp.weixin.qq.com/s/xVFlF9qTf9c74Emmdm0DqA 在繁忙的工作中&#xff0c;持…

如何在postman上提交文件格式的数据

如何在postman上提交文件格式的数据 今天在写一个文件上传的功能接口时&#xff0c;想用postman进行提交&#xff0c;花了些时间才找到在postman提交文件格式的数据。记录一下吧&#xff01; 1.打开postman&#xff0c;选择POST提交方式&#xff0c;然后在Params那一行的Head…

代码随想录算法训练营DAY45|C++动态规划Part7|70.爬楼梯(进阶版)、322. 零钱兑换、279.完全平方数

文章目录 70.爬楼梯&#xff08;进阶版&#xff09;322. 零钱兑换思路CPP代码 279.完全平方数思路CPP代码 70.爬楼梯&#xff08;进阶版&#xff09; 卡码网&#xff1a;57. 爬楼梯 文章讲解&#xff1a;70.爬楼梯(进阶版) 322. 零钱兑换 力扣题目链接 文章讲解&#xff1a;322…