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,一经查实,立即删除!

相关文章

手把手教你实现贪吃蛇

前言 在实现贪吃蛇前&#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;获取…

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…

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

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

Cronjob提权

参考&#xff1a; https://redpomelo.xyz/archives/1699953656909 前言 提权为该靶机的精髓&#xff0c;Cronjob通常以root特权运行。如果我们可以成功篡改cronjob中 定义的任何脚本或二进制文件&#xff0c;那么我们可以以root特权执行任意 代码。 什么是Cronjob&#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;但由于原始数据在命名、…

ai写作强大,ai写作哪个软件最好用?

在当今数字化时代&#xff0c;ai技术的发展正以惊人的速度改变着我们的生活和工作方式。其中&#xff0c;ai写作作为一项令人瞩目的创新&#xff0c;展示了强大的文本生成能力。然而&#xff0c;随着各种ai写作软件的涌现&#xff0c;人们不禁困惑&#xff1a;哪个软件才是最好…

SQLite数据库中JSON 函数和运算符(二十七)

返回&#xff1a;SQLite—系列文章目录 上一篇:维护SQLite的私有分支&#xff08;二十六&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 ​1. 概述 默认情况下&#xff0c;SQLite 支持 29 个函数和 2 个运算符 处理 JSON 值。还有两个表值函数可用于分解 JSON 字…

大模型应用开发基础

AGI 时代&#xff0c;AI 无处不在&#xff0c;形成新的社会分层&#xff1a; AI 使用者&#xff0c;使用别人开发的 AI 产品AI 产品开发者&#xff0c;设计和开发 AI 产品基础模型相关&#xff0c;训练基础大模型&#xff0c;或为大模型提供基础设施 越向下层&#xff0c;重要…

MEMENTO(备忘录)-- 对象行为型模式

意图&#xff1a; 在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 别名&#xff1a; Token 动机&#xff1a; 有时必要记录一个对象的内部状态。 适用性&#xff1a; a. 必…

【云计算】云数据中心网络(五):对等连接

《云网络》系列&#xff0c;共包含以下文章&#xff1a; 云网络是未来的网络基础设施云网络产品体系概述云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC云数据中心网络&#xff08;二&#xff09;&#xff1a;弹性公网 IP云数据中心网络&#xff08;三&#xff09;…

跟TED演讲学英文:How AI could save (not destroy) education by Sal Khan

How AI could save (not destroy) education Link: How AI could save (not destroy) education Speaker: Sal Khan Date: April 2023 文章目录 How AI could save (not destroy) educationIntroductionVocabularyTranscriptSummary后记 Introduction Sal Khan, the founder…

遥瞻智慧:排水系统远程监控的卓越解决方案

遥瞻智慧&#xff1a;排水系统远程监控的卓越解决方案 在城市脉络的深层肌理中&#xff0c;排水系统犹如一条条隐秘的生命线&#xff0c;默默承载着城市的呼吸与律动。然而&#xff0c;如何以科技之眼&#xff0c;赋予这些无形网络以实时感知、精准调控的能力&#xff0c;使之…