MyBatis 学习(五)之 高级映射

目录

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 {//部门idprivate Integer deptId;//部门名称private String deptName;//部门有哪些员工private List<Employee> employees;// Getter、Setter、toString 方法省略
}

Employee 类

public class Employee {//员工idprivate 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 configurationPUBLIC "-//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 {//定义 SqlSessionSqlSession sqlSession = null;//定义 EmployeeMapper 对象private EmployeeMapper mapper = null;@Beforepublic 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 产生 sessionsqlSession = sqlSessionFactory.openSession();// 创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成 EmployeeMapper 的代理实现类mapper = sqlSession.getMapper(EmployeeMapper.class);}//查询所有员工数据@Testpublic void testSelectAll() {List<Employee> listEmployee = mapper.selectAll();for (Employee employee : listEmployee) {System.out.println(employee);}sqlSession.close();}//根据员工 id 查询数据@Testpublic void testSelectById() {Employee employee = mapper.selectEmpByEmpId(1);System.out.println(employee);sqlSession.close();}
}

测试结果

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

创建 DepartmentTest 测试类

public class DepartmentTest {//定义 SqlSessionSqlSession sqlSession = null;//定义 DepartmentMapper 对象private DepartmentMapper mapper = null;@Beforepublic 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 产生 sessionsqlSession = sqlSessionFactory.openSession();// 创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成 DepartmentMapper 的代理实现类mapper = sqlSession.getMapper(DepartmentMapper.class);}//查询所有部门数据@Testpublic void testSelectAll() {List<Department> listDepartment = mapper.selectAll();for (Department department : listDepartment) {System.out.println(department);}sqlSession.close();}//根据部门 id 查询 数据@Testpublic void testSelectById() {Department department = mapper.findDepartmentById(1);System.out.println(department);sqlSession.close();}
}

测试结果

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

4 参考文档

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频在线压缩

video2edit 一款免费的在线视频编辑软件&#xff0c;可以进行视频合并、视频剪辑、视频压缩以及转换视频格式等。 链接地址&#xff1a;在线视频编辑器和转换器 - 编辑&#xff0c;转换和压缩视频文件 打开视频压缩页面&#xff0c;上传想要压缩视频&#xff0c;支持MP4&…

【前端素材】推荐优质在线电影院商城电商网页Hyper平台模板(附源码)

一、需求分析 1、系统定义 在线电影商城是指一个通过互联网提供电影服务的平台&#xff0c;用户可以在该平台上浏览电影资源、租借或购买电影&#xff0c;以及观看在线影片。 2、功能需求 在线电影商城是指一个通过互联网提供电影服务的平台&#xff0c;用户可以在该平台上…

mybatisplus使用教程,京东物流java面试流程

造成雪崩的真实场景 1.4.1 服务提供者不可用 硬件故障:如网络故障、硬盘损坏等。 程序的 bug:如算法需要占用大量 CPU 的计算时间导致 CPU 使用率过高。 缓存击穿:比如应用刚重启&#xff0c;短时间内缓存是失效的&#xff0c;导致大量请求直接访问到了数据库&#xff0c;数…

【算法】二叉搜索树的插入、删除、转换操作

1 二叉搜索树的插入操作 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能…

动态内存分配

目录 存在动态内存分配的原因动态内存函数mallocfreecallocrealloc 常见的动态内存错误C/C程序的内存开辟柔性数组柔性数组的特点柔性数组的使用柔性数组的优势 存在动态内存分配的原因 内存开辟方式,例如&#xff1a; int val 20;在栈空间上开辟四个字节 char arr[10] { 0 …

一线互联网大厂中高级Android面试真题收录,记一次字节跳动Android社招面试

在开始回答前&#xff0c;先简单概括性地说说Linux现有的所有进程间IPC方式&#xff1a; 1. **管道&#xff1a;**在创建时分配一个page大小的内存&#xff0c;缓存区大小比较有限&#xff1b; 2. 消息队列&#xff1a;信息复制两次&#xff0c;额外的CPU消耗&#xff1b;不合…

C# 解决uploadify插件上传时造成session丢失问题

出现的问题&#xff1a; 在应用uploadify插件实现上传图片时&#xff0c;报了HTTP Error&#xff0c;经过在Network查看上传方法报错码是302&#xff0c;那这里就可以知道问题是什么了&#xff0c;HTTP 302是请求被重定向&#xff0c;如果你的uploadify处理上传方法有session验…

【论文笔记】An Effective Adversarial Attack on Person Re-Identification ...

原文标题&#xff08;文章标题处有字数限制&#xff09;&#xff1a; 《An Effective Adversarial Attack on Person Re-Identification in Video Surveillance via Dispersion Reduction》 Abstract 通过减少神经网络内部特征图的分散性攻击reid模型。 erbloo/Dispersion_r…

gcd+线性dp,[蓝桥杯 2018 国 B] 矩阵求和

一、题目 1、题目描述 经过重重笔试面试的考验&#xff0c;小明成功进入 Macrohard 公司工作。 今天小明的任务是填满这么一张表&#xff1a; 表有 &#xfffd;n 行 &#xfffd;n 列&#xff0c;行和列的编号都从 11 算起。 其中第 &#xfffd;i 行第 &#xfffd;j 个元素…

软件测试笔记(三):黑盒测试

1 黑盒测试概述 黑盒测试也叫功能测试&#xff0c;通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作是一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情况下&#xff0c;对程序接口进行测试&#xff0c;只检查程序功能是否按…

类加载的过程以及双亲委派模型

类加载&#xff0c;指的是java进程运行的时候&#xff0c;需要把.class文件从硬盘&#xff0c;读取到内存&#xff0c;并进行一系列的校验解析的过程。&#xff08;.class文件 > 类对象&#xff0c;硬盘 > 内存&#xff09; 类加载的过程&#xff0c;类加载的过程其实是在…

【Leetcode每日一刷】贪心算法|122.买卖股票的最佳时机 II、55. 跳跃游戏

一、122.买卖股票的最佳时机 II 力扣题目链接 &#x1f984;解题思路&#xff1a; 首先需要明确的几个点&#xff1a; 当前只能有最大一支股票每一天操作只能3选1&#xff1a;买or卖or休息 此外&#xff0c;对于贪心&#xff0c;总有像下面图示的一种直觉&#xff1a;如果…