mybatis一对一,多对一,一对多--使用自动映射避免繁琐的resultMap

头疼的一对一,多对一,一对多写法

我们知道,相比较hibernate,mybatis的一对一,一对多都比较繁琐,hibernate可以直接在实体类里面配置好映射关系,获取值的时候就能把一对一和一对多的对象带出来了,而mybatis需要用到resultMap,需要在resultMap中把实体类与表字段的对应关系一一写出来,如果遇到关联表有相同字段名,还要写别名,画风往往是这样的:

看着好像还行,但是要知道有些表可是有几十个字段的, 不仅要写resultMap,还要在sql中把所有列名写出来,这酸爽,看着就头疼,幸亏有个大杀器autoMapping,可以大大简化mapper.xml的代码量,下面来讲解下使用方法,让你对mybatis的一对一,一对多,多对一不再头疼.

autoMapping

有三个自动映射级别:

  • NONE - 禁用自动映射。只会设置手动映射的属性。
  • PARTIAL - 除了内部定义了嵌套结果映射的结果(联接)之外,其他都会自动映射。
  • FULL - 自动映射所有内容。

默认是partial,也就是当你resultMap中包含 association,collection等嵌套结果时是不会自动映射的,但是可以在resultMap中配置autoMapping="true"手动开启,为啥默认配置是partical自然是有原因的,因为表关联的时候很可能会引入相同的字段,这时自动映射可能会出现错误的结果,不过这个问题是有办法规避的

试验用sql

我们定义两张表,department部门表和employee员工表,每个员工属于一个部门,员工与部门是多对一的关系,部门与员工是一对多的关系,一对一的写法其实和多对一一样,就不另外介绍了

CREATE TABLE `department`  (`id` int(0) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',`create_time` date NULL DEFAULT NULL COMMENT '成立时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;CREATE TABLE `employee`  (`id` int(0) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`birthday` date NULL DEFAULT NULL,`job` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`department_id` int(0) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

多对一

定义一个EmployeeDTO,里面有员工所属部门的对象,在员工数据中返回所属部门,就实现了多对一的效果

@Getter
@Setter
public class EmployeeDTO extends Employee {private Department department;
}

多对一有两种实现方式,一种是表连接然后直接映射,还有一种是先查主表,再查关联表

表连接方式

可以看到,下面的代码开启了自动映射,并且sql中没有写字段名,直接通过*来取所有字段,这样是最简洁的写法,后续就算department加字段我们也不需要改resultMap了,但是这种写法遇到同名的字段就会有问题

<mapper namespace="cn.hollycloud.server.mapper.EmployeeMapper"><!-- 错误的示范 --><resultMap id="BaseResultMap" type="cn.hollycloud.server.dto.EmployeeDTO" autoMapping="true"><id column="id" property="id" /><association property="department" javaType="cn.hollycloud.server.entity.Department" autoMapping="true"></association></resultMap><select id="listAll" resultMap="BaseResultMap">select e.*,d.* from employee eleft join department d on e.department_id = d.id</select></mapper>

返回结果中可以看到,department中注入了员工的id和名字,这显然不是我们想要的结果,该如何解决呢?

我们需要把 子表中同名的字段命名为别名,并且在resultMap中做单独的映射,正确版本如下:

<mapper namespace="cn.hollycloud.server.mapper.EmployeeMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="cn.hollycloud.server.dto.EmployeeDTO" autoMapping="true"><id column="id" property="id" /><association property="department" javaType="cn.hollycloud.server.entity.Department" autoMapping="true"><id column="d_id" property="id" /><result column="d_name" property="name" /></association></resultMap><select id="listAll" resultMap="BaseResultMap">select e.*,d.id d_id,d.name d_name,d.* from employee eleft join department d on e.department_id = d.id</select>
</mapper>

可以看到,结果是正确的

关于重名的疑虑

看看上面的sql,select e.*,d.id d_id,d.name d_name,d.*,这个sql展开就是select e.id,e.name,d.id d_id,d.name d_name,d.id,d.name,其实返回的字段还是有重名的,如何能确定resultMap一定能找到正确的值呢?我们可以看看源码

DefaultResultSetHandler的getRowValue

 一路跟进去我们发现最后其实就是调用的resultSet.getString(columnName),而这个方法优先返回第一个遇到的列的值,所以employee注入的是e.name而不是d.name,但是如果你写成select d.*,e.*也就是把d放前面就会注入部门的name,这点需要注意

子查询方式

子查询方式实现方式跟hibernate类似,先是查主表,下面例子中就是查员工表,再根据员工表中的department_id去查所属部门,优点是不用考虑重名问题,直接能够自动映射好,缺点是效率没表连接高,比如主表有10条数据,它先查出10条数据,再一个个根据id去查子表,要执行11条sql

association中column="{id = department_id}"的意思是把主表中department_id赋值给id,再把id作为参数传入getDepartmentById中

<mapper namespace="cn.hollycloud.server.mapper.EmployeeMapper"><select id="listAll1" resultMap="BaseResultDto">select * from employee</select><select id="getDepartmentById" resultType="cn.hollycloud.server.entity.Department">select * from department where id = #{id}</select><!-- 通用查询映射结果 --><resultMap id="BaseResultDto" type="cn.hollycloud.server.dto.EmployeeDTO"><id column="id" property="id" /><association property="department" select="getDepartmentById" column="{id = department_id}"/></resultMap>
</mapper>

一对多

一对多跟多对一其实差不多,只要association改成collection就行了,下面的例子中返回的部门数据中包含部门下所有员工,就是一对多了,一对多也有两种实现方式,表连接和子查询,表连接优点是效率高,缺点是需要考虑重名,不能分页,子查询优点是写法简洁,可以分页,缺点是效率不高

@Getter
@Setter
public class DepartmentDTO extends Department {private List<Employee> employees;
}

表连接方式

<mapper namespace="cn.hollycloud.server.mapper.DepartmentMapper"><resultMap id="BaseResultMap" type="cn.hollycloud.server.dto.DepartmentDTO" autoMapping="true"><id column="id" property="id" /><collection property="employees" ofType="cn.hollycloud.server.entity.Employee" autoMapping="true"><id column="e_id" property="id" /><result column="e_name" property="name" /></collection></resultMap><select id="listAll" resultMap="BaseResultMap">select d.*, e.id e_id, e.name e_name, e.* from department d left join employee e on e.department_id = d.id</select>
</mapper>

子查询方式

<mapper namespace="cn.hollycloud.server.mapper.DepartmentMapper"><resultMap id="BaseResultDTO" type="cn.hollycloud.server.dto.DepartmentDTO"><id column="id" property="id" /><collection property="employees" ofType="cn.hollycloud.server.entity.Employee"select="listByDepartmentId" column="{id = id}"/></resultMap><select id="listByDepartmentId" resultType="cn.hollycloud.server.entity.Employee">select * from employee where department_id = #{id}</select><select id="listAll1" resultMap="BaseResultDTO">select * from department</select>
</mapper>

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

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

相关文章

红黑树(Red-Black Tree)

红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff0c;它具有以下特性&#xff1a; 1. 每个节点要么是红色&#xff0c;要么是黑色。 2. 根节点是黑色的。 3. 每个叶子节点&#xff08;NIL节点&#xff09;是黑色的。 4. 如果一个节点是红色的&am…

手把手教你实现贪吃蛇

前言 在实现贪吃蛇前&#xff0c;我们需要熟练地掌握C语言知识&#xff0c;对初阶数据结构中的链表有一定的掌握&#xff0c;并且我们还会使用到Win 32 API 的知识&#xff0c;下面我会对需要使用到的API接口函数进行解释。最终的代码我放在后面&#xff0c;有需要的可以自取。…

探索C语言数据结构:利用顺序表完成通讯录的实现

在好久之前我就已经学习过顺序表&#xff0c;但是在前几天再次温习顺序表的时候&#xff0c;我惊奇的发现顺序编表可以完成我们日常使用的通讯录的功能&#xff0c;那么今天就来好好通过博客总结一下通讯录如何完成吧。 常常会回顾努力的自己&#xff0c;所以要给自己的努力留…

OpenHarmony其他工具类—lua

简介 Lua是一种功能强大、高效、轻量级、可嵌入的脚本语言。 支持过程编程、面向对象编程、函数编程、数据驱动编程和数据描述。 下载安装 直接在OpenHarmony-SIG仓中搜索lua并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 将下载的lua库代码存在以下路径&#…

Java Web3-2 - tomcat

https://github.com/heibaiying/Full-Stack-Notes/blob/master/notes/Tomcat_架构解析.md https://zhuanlan.zhihu.com/p/40249834 早期&#xff0c;web技术主要用于浏览静态页面 时间发展&#xff0c;用户已经不满足于仅浏览静态页面。用户需要一些交互操作&#xff0c;获取…

服务器有哪些特性?

服务器是计算机的一种&#xff0c;但是和普通的计算机是不同的&#xff0c;服务器比普通计算机的运行速度更快、负载能力更高&#xff0c;可以在网络中为其它客户机或是大型设备提供计算或者是应用服务&#xff0c;服务器有着高速的CPU运算能力、能够进行长时间的运行有着更好的…

STM32G431RBT6之时钟树配置与生成工程

默认大家都下载了蓝桥杯嵌入式资源包了哈. 首先,打开cubumx,修改RCC与SYS. 打开并观察原理图,发现晶振是24Mhz. 第一步,打开Clock Configuration. 第二步,修改晶振为原理图相对应的24Mhz. 第三步,切换到HSE. 第四步,切换到PLLCLK. 第五步,设置HCLK为80Mhz(15届真题要求为8…

洛谷P1057 [NOIP2008 普及组] 传球游戏

#include<iostream> using namespace std; int n;// n个人传球游戏 默认开始球在编号为1的位置 int m;// 传递m次球 int main(){cin>>n>>m;// 动态转方程&#xff1a;// 球传递到编号为k人的手中// 种类总数 传递到k-1编号种类总数 传递到k1编号种类总数//…

wsl2 Ubuntu子系统内存只有一半的解决办法

物理机的内存是64G&#xff0c;在wsl2安装完Ubuntu20.04后&#xff0c;输入命令&#xff1a; free -g 发现只有32G&#xff0c;原因是默认只能获得物理机一半的内存&#xff1a; WSL 中的高级设置配置 | Microsoft Learn 因此可手动修改为与物理机同等大小&#xff1a; 1&a…

后端开发面经系列 -- 哔哩哔哩C++后端一面

B站C后端开发一面 公众号&#xff1a;阿Q技术站 来源&#xff1a;https://www.nowcoder.com/discuss/550638808786661376 1、MySQL默认16KB的页大小会不会有什么问题&#xff1f;为什么使用16KB作为页面的默认大小&#xff1f; MySQL默认的页大小&#xff08;或称为数据页、表…

【数据库】数据库为什么比电子表格快

为了更深入地了解SQL数据库用于加速查询的特定算法和机制&#xff0c;让我们关注索引和查询优化。与在CSV等平面文件中进行线性搜索相比&#xff0c;这些基本方面使数据库中的查询速度更快。 1。索引 数据库中的索引有点类似于书籍中的索引&#xff0c;它允许你快速定位特定的…

再拓信创版图-Smartbi Insight V11与东方国信CirroData数据库完成兼容适配认证

近日&#xff0c;思迈特商业智能与数据分析软件 [简称&#xff1a;Smartbi Insight] V11与北京东方国信科技股份有限公司 &#xff08;以下简称东方国信&#xff09;CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试&#xff0c;两款产品能够达到通用兼容性要…

i18next serverSideTranslations 的使用

i18next 是一个流行的国际化&#xff08;i18n&#xff09;库&#xff0c;它可以帮助应用程序中实现多语言支持。next-i18next 是 Next.js 中与 i18next 集成的官方插件&#xff0c;它提供了一种简单的方式来在 Next.js 应用程序中实现国际化。 serverSideTranslations 是 next…

PyTorch中的常见乘法运算(*、@、Mul、Matmul)

哈达玛积&#xff1a;torch.mul()、torch.dot()、* 两个相同尺寸的张量相乘&#xff0c;然后对应元素的相乘就是哈达玛积&#xff0c;这种乘法要求参与运算的矩阵唯独相同&#xff0c;运算结果还是一个相同维度的矩阵。在这个运算中&#xff0c;torch.mul()和*以及torch.dot()…

Cronjob提权

参考&#xff1a; https://redpomelo.xyz/archives/1699953656909 前言 提权为该靶机的精髓&#xff0c;Cronjob通常以root特权运行。如果我们可以成功篡改cronjob中 定义的任何脚本或二进制文件&#xff0c;那么我们可以以root特权执行任意 代码。 什么是Cronjob&#xf…

JS - 分支结构、循环结构

关于JavaScript中的分支结构和循环结构&#xff0c;其实和其他编程语言区别也不是很大&#xff0c;只是js对这两种结构进行了相应的扩充&#xff0c;当然本质上并没有变化&#xff0c;本篇就是一篇记录博主在学习前端路上的总结和敲过的demo&#xff0c;实际上水份很大&#xf…

Jmeter 性能-死锁问题定位+分析

1、环境搭建 ①准备脚本&#xff0c;执行压测 ②用Jstack 打印日志 jstack 112759 >dead.log ③下载日志到本地 sz dead.log 2、问题定位 ①打开dead.log&#xff0c;搜索deadlock ②查看死锁的线程 ③查看死锁位置 3、问题分析 ①下载死锁的类文件 Sz CaseControlle…

使用iMazing对iPhone有影响吗 为什么iPhone都会装iMazing来管理 苹果手机imazing安装

随着科技的迅速发展&#xff0c;智能手机已成为我们日常生活中不可或缺的一部分&#xff0c;iPhone手机占据了智能手机市场的大部分&#xff0c;也有着庞大的用户基础。随着时代的发展&#xff0c;用户对于更高级的设备管理工具的需求也随之增加。iMazing作为一款强大的设备管理…

美业连锁门店收银系统源码-如何查看收款门店对应的加盟商?

美业管理系统源码 博弈美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 促销活动 PC管理后台、手机APP、iPad APP、微信小程序 第一步&#xff1a; 登录pc管理后端 第二步&#xff1a; 进入企业组织管理-门店管理&a…

pandas/python 一个实战小案例

上次写坦克游戏的时候&#xff0c;接触了一点pandas&#xff0c;当时只是简单了解了一下如何遍历行和列并获取值来替换图片&#xff0c;想更多了解pandas。正好有一些数据需要筛选&#xff0c;试试能不能用通过代码实现。虽然总的来说不复杂&#xff0c;但由于原始数据在命名、…