MyBatis 学习(五)之 高级映射

news2024/9/21 17:51:37

目录

1 association 和 collection 介绍

2 案例分析

3 一对一关联和一对多关联

4 参考文档


1 association 和 collection 介绍

        在之前的 SQL 映射文件中提及了 resultMap 元素的 association collection 标签,这两个标签是用来关联查询的,它们的属性几乎一致,以下是对它们属性的描述,红色标注的是常用属性。

属性描述
property实体类属性名
column数据库字段名或者其别名
javaType实体类属性的 Java 类型
jdbcType数据库列的数据类型
ofType指定关联对象的类型。它通常用于泛型类型的情况,以确保正确的类型转换
select指定一个子查询,用于加载关联的对象
fetchType用于控制加载策略,比如立即加载还是延迟加载。常见的取值有 lazy(延迟加载)和 eager(立即加载)
resultMap引用预定义的结果映射,以便更灵活地配置关联对象的映射规则
resultSet指定结果集的名称,以便在多结果集的情况下进行区分
autoMapping是否自动映射所有列到目标对象的属性上。默认为 true,表示自动映射;设置为 false 则表示不自动映射
columnPrefix当使用内连接查询时,这个属性可以用来指定前缀,以区分关联表的列名
foreignColumn指定外键对应的列名
notNullColumn指定一个列名,只有当该列的值不为 null 时,才会执行关联查询
typeHandler自定义的类型处理器

2 案例分析

以典型的 员工 (Employee) 和部门 (Department) 为例

  • 一个员工只能在一个部门:Employee -> Department(一对一)
  • 一个部门可以包含多个员工:Department -> Employee(一对多)

以用户 (User) 和角色 (Role) 为例,两者成了一个双向的一对多,从而变成了多对多,不做介绍

  • 一个用户可以拥有多个角色:User -> Role(一对多)
  • 一个角色可以赋予多个用户:Role -> User(一对多)

表 department 和 表 employee

# 创建 department 表
drop table if exists department;
create table department(
department_id int(11) primary key auto_increment, #主键,自增
department_name varchar(255)
)charset=utf8;

# 插入数据
insert into department(department_name) values
('开发部'),
('人力资源部'),
('市场营销部'),
('财务部'),
('行政部'),
('监察部'),
('客服服务部');

# 创建 employee 表
drop table if exists employee;
create table employee(
employee_id int(11) primary key auto_increment, #主键,自增
employee_name varchar(255),
employee_age int(11),
employee_sex char(32),
employee_email varchar(255),
employee_address varchar(255),
department_id int(11)
)charset=utf8;

# 插入数据
insert into employee values
(1, '唐浩荣', 23, 1, '15477259875@163.com', '中国上海浦东区', 1),
(2, '黄飞鸿', 32, 1, '86547547@qq.com', '大清广东', 2),
(3, '十三姨', 18, 0, '520520520@gmail.com', '大清广东', 3),
(4, '纳兰元述', 28, 1, '545627858@qq.com', '大清京师', 5),
(5, '梁宽', 31, 1, '8795124578@qq.com', '大清广东', 7),
(6, '蔡徐坤', 20, 0, '4257895124@gmail.com', '四川成都', 4),
(7, '杨超越', 21, 0, '8746821252@qq.com', '中国北京', 7),
(8, '马保国', 66, 1, '6666666666@qq.com', '广东深圳', 6),
(9, '马牛逼', 45, 1, 'asdfg45678@163.com', '湖北武汉', 3);

3 一对一关联和一对多关联

工程目录

Department 类

public class Department {
    //部门id
    private Integer deptId;
    //部门名称
    private String deptName;

    //部门有哪些员工
    private List<Employee> employees;

    // Getter、Setter、toString 方法省略
}

Employee 类

public class Employee {
    //员工id
    private Integer empId;
    //员工名称
    private String empName;
    //员工年龄
    private Integer empAge;
    //员工性别
    private Integer empSex;
    //员工邮箱
    private String empEmail;
    //员工地址
    private String empAddress;

    //员工所属部门,和部门表构成一对一的关系,一个员工只能在一个部门
    private Department department;

    // Getter、Setter、toString 方法省略
}

创建 DepartmentMapper

public interface DepartmentMapper {
    //查询所有数据
    @Select("select * from department")
    @Results(id = "deptMap1", value = {
            @Result(property = "deptId", column = "department_id"),
            @Result(property = "deptName", column = "department_name"),
            // 一对多关联对象
            // 根据 department_id 来比较
            @Result(property = "employees", column = "department_id",
                many = @Many(select = "com.mapper.EmployeeMapper.selectEmpByDeptId"))
    })
    List<Department> selectAll();
    // 根据 id 查找部门
    @Select("select * from department where department_id = #{id}")
    @Results(id = "deptMap2", value = {
            @Result(property = "deptId", column = "department_id"),
            @Result(property = "deptName", column = "department_name")
    })
    Department findDepartmentById(int id);
}

创建 EmployeeMapper

public interface EmployeeMapper {
    //查询所有数据
    @Select("select * from employee")
    @Results(id = "empMap1", value = {
            @Result(property = "empId", column = "employee_id", id = true),
            @Result(property = "empName", column = "employee_name"),
            @Result(property = "empAge", column = "employee_age"),
            @Result(property = "empSex", column = "employee_sex"),
            @Result(property = "empEmail", column = "employee_email"),
            @Result(property = "empAddress", column = "employee_address"),
            // 一对一关联对象
            // 根据 department_id 来比较
            @Result(property = "department", column = "department_id",
                    one = @One(select = "com.mapper.DepartmentMapper.findDepartmentById"))}

    )
    List<Employee> selectAll();
    //根据员工id查询数据
    @Select("select * from employee where employee_id = #{id}")
    @ResultMap("empMap1")
    Employee selectEmpByEmpId(@Param("id") int empId);

    // 根据 department_id 查询数据
    @Select("select * from employee where department_id = #{id}")
    @ResultMap("empMap1")
    Employee selectEmpByDeptId(@Param("id") int deptId);
}

log4j.properties

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

mysql.properties

url=jdbc:mysql://localhost:3306/study?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
name=root
password=123456
driver=com.mysql.cj.jdbc.Driver

MyBatis 配置文件 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 通过properties标签,读取java配置文件的内容 -->
    <properties resource="mysql.properties" />
    <!-- 配置环境.-->
    <environments default="development">
        <environment id="development">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象源 -->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="url" value="${url}" />
                <property name="username" value="${name}" />
                <property name="password" value="${password}" />
                <property name="driver" value="${driver}" />
            </dataSource>
        </environment>
    </environments>
    <!--通过包 package 引入 SQL 映射文件-->
    <mappers>
        <package name="com.mapper"/>
    </mappers>
</configuration>

创建 EmployeeTest 测试类

public class EmployeeTest {
    //定义 SqlSession
    SqlSession sqlSession = null;
    //定义 EmployeeMapper 对象
    private EmployeeMapper mapper = null;

    @Before
    public void getSqlSession() throws IOException {
        //加载 mybatis 全局配置文件 Resources
        // 原 InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //创建 SqlSessionFactory 对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //根据 sqlSessionFactory 产生 session
        sqlSession = sqlSessionFactory.openSession();
        // 创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成 EmployeeMapper 的代理实现类
        mapper = sqlSession.getMapper(EmployeeMapper.class);
    }

    //查询所有员工数据
    @Test
    public void testSelectAll() {
        List<Employee> listEmployee = mapper.selectAll();
        for (Employee employee : listEmployee) {
            System.out.println(employee);
        }
        sqlSession.close();
    }

    //根据员工 id 查询数据
    @Test
    public void testSelectById() {
        Employee employee = mapper.selectEmpByEmpId(1);
        System.out.println(employee);
        sqlSession.close();
    }
}

测试结果

查询所有员工数据,包括员工所在部门(一个员工属于一个部门)

创建 DepartmentTest 测试类

public class DepartmentTest {
    //定义 SqlSession
    SqlSession sqlSession = null;
    //定义 DepartmentMapper 对象
    private DepartmentMapper mapper = null;

    @Before
    public void getSqlSession() throws IOException {
        //加载 mybatis 全局配置文件 Resources
        // 原 InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //创建 SqlSessionFactory 对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //根据 sqlSessionFactory 产生 session
        sqlSession = sqlSessionFactory.openSession();
        // 创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成 DepartmentMapper 的代理实现类
        mapper = sqlSession.getMapper(DepartmentMapper.class);
    }

    //查询所有部门数据
    @Test
    public void testSelectAll() {
        List<Department> listDepartment = mapper.selectAll();
        for (Department department : listDepartment) {
            System.out.println(department);
        }
        sqlSession.close();
    }

    //根据部门 id 查询 数据
    @Test
    public void testSelectById() {
        Department department = mapper.findDepartmentById(1);
        System.out.println(department);
        sqlSession.close();
    }
}

测试结果

查询所有部门信息,包括该部门有哪些员工(一个部门有多个员工)

4 参考文档

篇篇“参考”这位博主的文档。。。不过确实写的挺好的

Mybatis3详解(八)----高级映射之一对一映射 - 唐浩荣 - 博客园 (cnblogs.com)

Mybatis3详解(九)----高级映射之一对多映射 - 唐浩荣 - 博客园 (cnblogs.com)

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

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

相关文章

指针与malloc动态内存申请,堆和栈的差异

定义了两个函数print_stack()和print_malloc()&#xff0c;分别演示了两种不同的内存分配方式&#xff1a;栈内存和堆内存。然后在main()函数中调用这两个函数&#xff0c;并将它们返回的指针打印出来。 由于print_stack()中的数组c是在栈上分配的&#xff0c;当函数返回后&…

LabVIEW非接触式电阻抗层析成像系统

LabVIEW非接触式电阻抗层析成像系统 非接触式电阻抗层析成像&#xff08;NEIT&#xff09;技术以其无辐射、非接触、响应速度快的特点&#xff0c;为实时监测提供了新的解决方案。基于LabVIEW的电阻抗层析成像系统&#xff0c;实现了数据的在线采集及实时成像&#xff0c;提高…

黑马JavaWeb课程中安装vue脚手架出现的问题

1 安装node.js 要想前端工程化&#xff0c;必须安装node.js&#xff0c;前端工程化的环境。 在成功安装node.js后&#xff0c; 修改全局包安装路径为Node.js安装目录&#xff0c; 修改npm镜像源为淘宝镜像源&#xff0c;这里出现第一个问题&#xff0c;视频中给的淘宝镜像为&…

力扣SQL50 无效的推文 查询

Problem: 1683. 无效的推文 思路 &#x1f468;‍&#x1f3eb; 参考 char_length(str)&#xff1a;计算 str 的字符长度length(str)&#xff1a;计算 str 的字节长度 Code select tweet_id from Tweets where char_length(content) > 15;

G8-ACGAN理论

本文为&#x1f517;365天深度学习训练营 中的学习记录博客 原作者&#xff1a;K同学啊|接辅导、项目定制 我的环境&#xff1a; 1.语言&#xff1a;python3.7 2.编译器&#xff1a;pycharm 3.深度学习框架Pytorch 1.8.0cu111 一、对比分析 前面的文章介绍了CGAN&#xf…

面试官上来就让手撕HashMap的7种遍历方式,当场愣住,最后只写出了3种

HashMap的7种遍历方式 四大类遍历方式 其实在JDK1.8之前&#xff0c;遍历的方式远没有现在这样多&#xff0c;为了提高开发效率&#xff0c;JDK1.8开始引入了Stream流、Lambda 表达式等新特性&#xff0c;这让很多数据结构的遍历方式也丰富了起来。目前&#xff0c;常用的遍历方…

Node.js中的缓存策略和缓存技巧

在Node.js中&#xff0c;缓存策略和缓存技巧是提升应用性能和用户体验的关键因素。通过有效地利用缓存&#xff0c;我们可以显著减少系统资源的消耗&#xff0c;加快数据访问速度&#xff0c;从而提升整体的网站性能。本文将针对Node.js中的缓存策略和缓存技巧展开深入探讨&…

Windows下卸载JDK

操作步骤&#xff1a; 直接到windows程序卸载面板进行卸载 然后删除已配置的环境变量

TDengine 研发分享:利用 Windbg 解决内存泄漏问题的实践和经验

内存泄漏是一种常见的问题&#xff0c;它会导致程序的内存占用逐渐增加&#xff0c;最终导致系统资源耗尽或程序崩溃。AddressSanitizer (ASan) 和 Valgrind 是很好的内存检测工具&#xff0c;TDengine 的 CI 过程就使用了 ASan 。不过这次内存泄漏问题发生在 Windows 下&#…

设置matplotlib的style和rcParams

在matplotlib文档中&#xff0c;有3中设置matplot的方法&#xff0c;见文档 https://matplotlib.org/stable/users/explain/customizing.html 目前用得比较多的是设置rcParams&#xff0c;而设置rcParams也有两种方式。下面以 plot的cycler为例进行说明。 cycler就是定义的一些…

13.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-如果没有工具就创造工具

内容参考于&#xff1a; 易道云信息技术研究院VIP课 上一个内容 &#xff1a;12.游戏网络通信存在的问题 现在把游戏网络的架构看了一个小小的大概&#xff0c;可以用它的接口发数据接收数据了&#xff0c;如果真正想用它这一套东西&#xff0c;真正核心不在于它的接口而在于…

私域必备宝藏工具:多微信统一管理聚合聊天

对于私域流量运营者来说&#xff0c;如何高效管理多个微信号成为了一道难题。 不过不用担心&#xff0c;通过微信管理系统&#xff0c;可以实现多个微信同时登录&#xff0c;同一个界面内聚合聊天&#xff0c;省去来回切换账号的步骤。而且&#xff0c;还有很多非常实用且便捷…

Chrome插件 | WEB 网页数据采集和爬虫程序

无边无形的互联网遍地是数据&#xff0c;品类丰富、格式繁多&#xff0c;包罗万象。数据采集&#xff0c;或说抓取&#xff0c;就是把分散各处的内容&#xff0c;通过各种方式汇聚一堂&#xff0c;是个有讲究要思考的体力活。君子爱数&#xff0c;取之有道&#xff0c;得注意遵…

种花

分情况&#xff1a; 第一盆k种选择&#xff0c;之后全部k-1种选择 每次相乘结果对1e97取模 #include <iostream> #include <vector> #include <algorithm> using namespace std; #define endl \n const int N 1e9 7;int main() {ios::sync_with_stdio(f…

camunda7流程版本的控制和使用

1、流程定义的版本控制 从本质上讲&#xff0c;业务流程是长期运行的&#xff0c;流程实例可能会持续数周或数月。同时&#xff0c;流程实例的状态将存储到数据库中。但是&#xff0c;即使仍有正在运行的实例&#xff0c;您也可能需要更改流程定义。 流程引擎支持此功能&…

笔记73:ROS中的各种消息包

参考视频&#xff1a; 33.ROS 的标准消息包 std_msgs_哔哩哔哩_bilibili 34. ROS 中的几何包 geometry_msgs 和 传感器包 sensor_msgs_哔哩哔哩_bilibili 标准消息包&#xff1a;std_msgs常用消息包&#xff1a;common_msgs导航消息包&#xff1a;nav_msgs几何消息包&#xf…

C++数据结构与算法——二叉树的属性

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

C++——String(1)

目录 1. 为什么学习string类&#xff1f; 1.1 C语言中的字符串 1.2 相关题目 2. 标准库中的string类 2.1 string类&#xff08;了解一下&#xff09; 2.2 string类的常用接口说明 1. string类对象的常见构造 2. string类对象的容量操作 3. string类对象的访问及遍历操作…

瑞_Redis_Redis的Java客户端

文章目录 1 Redis的Java客户端1.1 Jedis快速入门1.1.1 入门案例1.1.1.1 项目构建1.1.1.2 引入依赖1.1.1.3 建立连接1.1.1.4 释放资源1.1.1.5 测试1.1.1.6 完整测试类代码 1.1.2 Jedis连接池1.1.2.1 连接池工具类1.1.2.2 改造原始代码 &#x1f64a; 前言&#xff1a;本文章为瑞…

【Java程序设计】【C00327】基于Springboot的高校教师教研信息填报系统(有论文)

基于Springboot的高校教师教研信息填报系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的高校教师教研信息填报系统&#xff0c;本系统有管理员、教研管理以及教研人员三种角色&#xff1b; 管理员&#xff1a…