当前位置: 首页 > article >正文

告别手写SQL!用mybatis-plus-join搞定SpringBoot多表查询(附完整代码)

告别手写SQL用mybatis-plus-join搞定SpringBoot多表查询附完整代码还在为复杂的多表关联查询而烦恼吗每次看到项目里那些冗长的XML映射文件和注解SQL就头疼如果你已经熟悉MyBatis-Plus的基础CRUD操作却还在为联表查询手动编写SQL而苦恼那么mybatis-plus-join正是你需要的解决方案。这个基于MyBatis-Plus的扩展框架能够让你用Lambda表达式或QueryWrapper的方式优雅地实现多表查询完全告别手写SQL的繁琐。我们将通过一个典型的后台管理系统案例用户-角色-权限带你体验从传统SQL到现代化链式调用的转变感受开发效率的显著提升。1. 为什么选择mybatis-plus-join在传统的MyBatis-Plus开发中单表CRUD操作已经足够简便但一旦遇到多表关联查询开发者往往不得不回归到原始的SQL编写方式。这不仅增加了代码量还带来了以下问题维护成本高SQL语句分散在XML文件或注解中修改时需要多处查找可读性差复杂的JOIN语句难以直观理解业务逻辑类型不安全字符串形式的字段名容易拼写错误且IDE无法提供智能提示调试困难动态SQL拼接出错时难以定位问题mybatis-plus-join的出现完美解决了这些痛点它保留了MyBatis-Plus简洁的API风格同时扩展了强大的多表关联能力。以下是它的核心优势// 传统方式 vs mybatis-plus-join方式对比 String sql SELECT u.id, u.name, r.role_name FROM user u JOIN user_role_mapping m ON u.id m.user_id JOIN role r ON m.role_id r.id WHERE u.status 1; // 使用mybatis-plus-join ListUserRoleVO result userService.selectJoinList(UserRoleVO.class, new MPJLambdaWrapperUser() .select(User::getId, User::getName) .selectAs(Role::getRoleName, UserRoleVO::getRoleName) .innerJoin(UserRoleMapping.class, UserRoleMapping::getUserId, User::getId) .innerJoin(Role.class, Role::getId, UserRoleMapping::getRoleId) .eq(User::getStatus, 1) );2. 环境准备与基础配置2.1 项目初始化首先创建一个标准的SpringBoot项目并添加必要的依赖dependencies !-- MyBatis-Plus核心依赖 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.1/version /dependency !-- mybatis-plus-join扩展 -- dependency groupIdcom.github.yulichang/groupId artifactIdmybatis-plus-join-boot-starter/artifactId version1.4.7/version /dependency !-- 数据库驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId /dependency !-- 连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.1.6/version /dependency !-- Lombok简化代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /dependency /dependencies2.2 数据库配置在application.yml中配置数据源和MyBatis-Plus相关属性spring: datasource: url: jdbc:mysql://localhost:3306/test_db?useSSLfalseserverTimezoneUTC username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource mybatis-plus: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.entity configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true2.3 实体类与Mapper改造使用MyBatisX插件生成基础代码后需要对Mapper进行改造// 传统Mapper接口 public interface UserMapper extends BaseMapperUser {} // 改造为支持join的Mapper public interface UserMapper extends MPJBaseMapperUser {}同样地Service层也需要相应调整public interface UserService extends MPJBaseServiceUser {} Service public class UserServiceImpl extends MPJBaseServiceImplUserMapper, User implements UserService {}3. 核心用法详解3.1 基础联表查询假设我们需要查询用户及其角色信息首先创建VO类Data public class UserRoleVO { private Long userId; private String userName; private Long roleId; private String roleName; }然后使用LambdaWrapper实现查询public ListUserRoleVO getUserWithRoles() { return userService.selectJoinList(UserRoleVO.class, new MPJLambdaWrapperUser() .select(User::getId, User::getName) .selectAs(User::getId, UserRoleVO::getUserId) .selectAs(User::getName, UserRoleVO::getUserName) .innerJoin(UserRoleMapping.class, UserRoleMapping::getUserId, User::getId) .innerJoin(Role.class, Role::getId, UserRoleMapping::getRoleId) .select(Role::getId, Role::getRoleName) .selectAs(Role::getId, UserRoleVO::getRoleId) .selectAs(Role::getRoleName, UserRoleVO::getRoleName) ); }提示selectAs方法用于将实体字段映射到VO的不同属性名避免命名冲突3.2 复杂条件查询对于更复杂的查询场景mybatis-plus-join同样游刃有余。例如查询年龄大于18岁且拥有admin角色的用户public ListUser getAdultAdmins() { return userService.selectJoinList(User.class, new MPJLambdaWrapperUser() .selectAll(User.class) .innerJoin(UserRoleMapping.class, UserRoleMapping::getUserId, User::getId) .innerJoin(Role.class, Role::getId, UserRoleMapping::getRoleId) .gt(User::getAge, 18) .eq(Role::getRoleName, admin) ); }3.3 多表分页查询分页是后台系统的常见需求mybatis-plus-join完美支持public PageUserRoleVO getUserRolePage(int current, int size) { return userService.selectJoinPage(new Page(current, size), UserRoleVO.class, new MPJLambdaWrapperUser() .selectAs(User::getId, UserRoleVO::getUserId) .selectAs(User::getName, UserRoleVO::getUserName) .innerJoin(UserRoleMapping.class, UserRoleMapping::getUserId, User::getId) .innerJoin(Role.class, Role::getId, UserRoleMapping::getRoleId) .selectAs(Role::getRoleName, UserRoleVO::getRoleName) .orderByAsc(User::getId) ); }4. 高级技巧与最佳实践4.1 动态表别名处理在复杂的多表关联场景中合理使用表别名可以避免字段冲突public ListUser getSameRoleUsers(String userName) { return userService.selectJoinList(User.class, new MPJLambdaWrapperUser() .setAlias(u1) .innerJoin(UserRoleMapping.class, m1, UserRoleMapping::getUserId, User::getId) .innerJoin(UserRoleMapping.class, m2, UserRoleMapping::getRoleId, UserRoleMapping::getRoleId) .innerJoin(User.class, u2, User::getId, UserRoleMapping::getUserId) .eq(u1.name, userName) .ne(u2.name, userName) .selectAll(User.class, u2) ); }4.2 性能优化建议虽然mybatis-plus-join简化了开发但仍需注意性能问题避免N1查询合理设计关联查询减少多次数据库往返选择性加载字段只查询需要的字段避免select *合理使用索引确保关联字段已建立适当索引缓存策略对频繁访问但不常变的数据考虑缓存4.3 与MyBatis-Plus原生功能结合mybatis-plus-join完全兼容MyBatis-Plus原有功能可以混合使用public ListUser getActiveAdmins() { // 先使用原生方法查询活跃用户 ListLong activeUserIds userService.lambdaQuery() .eq(User::getStatus, 1) .list() .stream() .map(User::getId) .collect(Collectors.toList()); // 再使用join查询管理员 return userService.selectJoinList(User.class, new MPJLambdaWrapperUser() .selectAll(User.class) .in(User::getId, activeUserIds) .innerJoin(UserRoleMapping.class, UserRoleMapping::getUserId, User::getId) .innerJoin(Role.class, Role::getId, UserRoleMapping::getRoleId) .eq(Role::getRoleName, admin) ); }在实际项目中根据团队习惯和项目规模可以逐步将老项目中的SQL迁移到mybatis-plus-join。对于特别复杂的查询仍然可以保留原生SQL方式两者并不冲突。

相关文章:

告别手写SQL!用mybatis-plus-join搞定SpringBoot多表查询(附完整代码)

告别手写SQL!用mybatis-plus-join搞定SpringBoot多表查询(附完整代码) 还在为复杂的多表关联查询而烦恼吗?每次看到项目里那些冗长的XML映射文件和注解SQL就头疼?如果你已经熟悉MyBatis-Plus的基础CRUD操作&#xff0c…...

HALCON深度学习效率翻倍?聊聊AI²接口与Intel独立显卡联手的那些事儿

HALCON深度学习效率翻倍?揭秘AI接口与Intel独立显卡的协同优化策略 在工业视觉检测领域,毫秒级的响应延迟可能意味着生产线上的数百万损失。当传统CPU推理遇到瓶颈时,开发者们开始将目光投向硬件加速方案。MVTec HALCON的AI加速器接口&#x…...

egergergeeert镜像免配置教程:网页端直接生成视觉概念图

egergergeeert镜像免配置教程:网页端直接生成视觉概念图 1. 平台介绍 egergergeeert是一款专为视觉创作者设计的文生图工具,通过简单的网页界面就能将文字描述转化为精美图像。无需任何编程基础,打开网页输入几个关键词,就能快速…...

扩散变换器中高效对数线性稀疏注意力机制解析

1. 高效扩散变换器的可训练对数线性稀疏注意力机制解析在视觉生成领域,扩散变换器(Diffusion Transformers, DiTs)已经成为当前最先进的骨干网络。然而,其自注意力机制固有的二次计算复杂度(O(N))从根本上限制了模型向长序列的扩展能力。传统解决方案如T…...

物联网轻量级通信协议设计:从二进制编码到嵌入式状态机实现

1. 项目概述:一个为物联网设备设计的轻量级通信协议最近在整理过往项目时,翻到了一个挺有意思的仓库:lobster-comm-protocol。这个名字乍一看有点怪,“龙虾通信协议”?其实这是我在几年前为一个资源极其受限的物联网项…...

Qianfan-OCR实操手册:Markdown表格渲染→复制粘贴至Notion/Typora无缝

Qianfan-OCR实操手册:Markdown表格渲染→复制粘贴至Notion/Typora无缝 1. 工具概述 基于百度千帆 Qianfan-OCR (InternVL 架构) 开发的单卡GPU专属文档解析工具,内置动态高分辨率图像预处理、多模式智能解析,支持高清文档/表格/公式/结构化…...

在Mac上构建本地AI API网关:afm的安装、配置与实战指南

1. 项目概述:在Mac上构建一个完全本地的AI API网关 如果你和我一样,是一个对隐私敏感、又热衷于在本地设备上折腾AI的开发者,那么你肯定对“把AI模型完全跑在自己的电脑上”这件事有执念。过去几年,我尝试过Ollama、LM Studio&am…...

如何为老旧Mac安装最新macOS:OpenCore Legacy Patcher完全指南

如何为老旧Mac安装最新macOS:OpenCore Legacy Patcher完全指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否有一台被苹果官方抛弃的老旧…...

【UNet 改进 | 注意机制篇】引入 SCSA 空间和通道协同注意力机制,即插即用,二次创新 (arXiv 2024)

本文教的是方法,也给出几种改进方法,二次创新结构,百变不离其宗,一文带你改进自己模型,科研路上少走弯路。 前言 在医学图像分割任务中,病灶区域往往形态各异、边界模糊,且经常与周围组织的对比度较低,这就要求分割模型具备极强的特征提取和辨别能力。传统的U-Net网络…...

B站视频转换终极指南:m4s-converter快速保存你的珍贵收藏

B站视频转换终极指南:m4s-converter快速保存你的珍贵收藏 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾因B站视频突然下架…...

漫画脸描述生成保姆级教程:解决中文描述歧义导致绘图偏差的技巧

漫画脸描述生成保姆级教程:解决中文描述歧义导致绘图偏差的技巧 1. 为什么你的漫画角色总是不像想象中那样? 你是不是经常遇到这样的情况:脑子里有一个完美的二次元角色形象,用中文描述出来让AI生成,结果却让人大跌眼…...

室内导航与三维场景生成技术解析与应用实践

1. 项目背景与核心价值室内导航与三维场景生成技术正在重塑建筑信息化、智能家居和虚拟现实等多个领域的发展格局。这个项目基于InternScenes数据集构建了一套完整的基准测试体系,为研究人员和开发者提供了评估算法性能的标准化平台。InternScenes作为新兴的大规模室…...

终极指南:如何用Nucleus Co-Op让单机游戏变身本地多人派对

终极指南:如何用Nucleus Co-Op让单机游戏变身本地多人派对 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop Nucleus Co-Op是一款革命性的…...

通过API调用日志回溯与分析特定时间段内的模型响应延迟

通过API调用日志回溯与分析特定时间段内的模型响应延迟 1. 审计日志功能概述 Taotoken平台为开发者提供了完整的API调用审计日志功能。所有通过平台发起的模型请求都会被记录,包括请求时间戳、响应耗时、模型标识等关键信息。这些数据以原始日志形式保留&#xff…...

5分钟上手Audiveris:免费开源乐谱识别神器,让纸质乐谱秒变数字宝藏

5分钟上手Audiveris:免费开源乐谱识别神器,让纸质乐谱秒变数字宝藏 【免费下载链接】audiveris Latest generation of Audiveris OMR engine 项目地址: https://gitcode.com/gh_mirrors/au/audiveris 还在为整理成堆的纸质乐谱而烦恼吗&#xff1…...

从‘采样开关’这个小零件,聊聊我是如何优化一款16位SAR ADC的(附关键仿真波形)

从采样开关到16位精度:一个SAR ADC设计项目的实战复盘 去年接手一个医疗设备信号采集模块的设计任务时,客户对ADC的线性度提出了近乎苛刻的要求——16位有效精度下INL必须控制在2LSB以内。项目初期使用传统CMOS传输门开关的测试结果让我至今记忆犹新&…...

3分钟解锁Windows 11 LTSC隐藏功能:微软商店一键安装完整指南

3分钟解锁Windows 11 LTSC隐藏功能:微软商店一键安装完整指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你是否曾经在Windows 11 LTS…...

acw_sc__v2

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!侵权通过名字绿泡泡联系删除博客。 逆向…...

8大网盘直链下载助手:彻底告别限速烦恼的智能解决方案

8大网盘直链下载助手:彻底告别限速烦恼的智能解决方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼…...

别再截图了!用Mathpix API+Python脚本,5分钟批量识别100张数学试卷

别再截图了!用Mathpix APIPython脚本,5分钟批量识别100张数学试卷 数学公式的数字化处理一直是教师、科研人员和学生的痛点。传统的手动输入方式效率低下,而截图识别工具又难以满足批量处理的需求。本文将介绍如何利用Mathpix的API接口&#…...

别再只调YOLOv5了!试试用OpenCV传统方法给车道线检测打个辅助(附完整代码)

轻量级车道线检测实战:当OpenCV传统方法遇上YOLOv5 在自动驾驶和辅助驾驶系统的开发中,车道线检测一直是个既基础又关键的环节。虽然像YOLOv5这样的深度学习模型在目标检测领域表现出色,但在实际工程落地时,我们常常会遇到模型体…...

《ubuntu22.04》_新系统的配置_20260418

1.安装输入法(fcitx) ibus有可能有问题,换成fcitx搜狗输入法可能更好一点,具体教程可以参考: https://shurufa.sogou.com/linux/guide ibus的安装教程: 1.1先安装程序 # 安装IBus和拼音输入法&#xf…...

微信AI助手集成实战:基于OpenClaw框架的双向通信通道插件详解

1. 项目概述:一个连接微信与AI的“双向桥”如果你正在寻找一个方案,能让你的AI助手(比如基于OpenClaw框架构建的Agent)直接接入微信,与好友或群聊进行自然对话,那么这个名为wechat-openclaw-channel的插件&…...

【C语言OTA调试黄金 checklist】:从Bootloader跳转到App校验,13步逐级验证,3分钟定位启动失败根因

更多请点击: https://intelliparadigm.com 第一章:C语言OTA调试黄金checklist总览 在嵌入式系统中,C语言实现的OTA(Over-The-Air)固件升级常因环境异构、资源受限和通信不可靠而引发静默失败。一份结构化、可验证的调…...

终极指南:如何用FanControl实现Windows风扇精准控制,告别噪音烦恼 [特殊字符]

终极指南:如何用FanControl实现Windows风扇精准控制,告别噪音烦恼 🎯 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: ht…...

嵌入式C代码FDA合规性崩溃预警(2024版DO-178C/IEC 62304双标对齐实战)

更多请点击: https://intelliparadigm.com 第一章:嵌入式C代码FDA合规性崩溃预警导论 FDA对嵌入式医疗设备的强制要求 美国食品药品监督管理局(FDA)在《General Principles of Software Validation》及《Cybersecurity in Medic…...

Haystack AI编排框架:从RAG到智能体的生产级应用构建指南

1. 项目概述:为什么我们需要一个AI编排框架? 如果你在过去一年里尝试过构建基于大语言模型的应用,大概率经历过这样的场景:兴奋地写了几行代码调用API,快速拼凑出一个能回答问题的原型,然后立刻被现实打脸…...

JavaScript中闭包Closure的定义及其底层形成机制分析

闭包是函数与其定义时词法作用域的组合,能访问并记住外部变量;需满足三条件:存在嵌套函数、内部函数被外部引用、实际访问外部局部变量;其本质是[[Environment]]静态绑定词法环境,变量因被闭包持有而从栈迁移至堆驻留。…...

WebPlotDigitizer终极教程:从零开始到高手,快速掌握图表数据提取的完整实战指南

WebPlotDigitizer终极教程:从零开始到高手,快速掌握图表数据提取的完整实战指南 【免费下载链接】WebPlotDigitizer Computer vision assisted tool to extract numerical data from plot images. 项目地址: https://gitcode.com/gh_mirrors/we/WebPlo…...

052、Python网络爬虫基础:requests库的使用

052、Python网络爬虫基础:requests库的使用 昨天帮实习生调试爬虫代码,又遇到了那个经典错误:ConnectionError: Max retries exceeded。小伙子对着屏幕挠头半小时,最后发现只是目标网站加了简单的User-Agent校验。这种问题在爬虫开发中太常见了——工具用起来简单,但细节…...