MyBatis注解开发实战:从基础CRUD到动态SQL与混合使用策略

发布时间:2026/8/4 3:48:07

MyBatis注解开发实战:从基础CRUD到动态SQL与混合使用策略
1. 从XML到注解为什么我选择在项目中混合使用如果你和我一样是从MyBatis的XML配置时代一路走过来的开发者那么第一次看到满篇的Select、Insert注解时心里多半会犯嘀咕这玩意儿能行吗XML多清晰啊SQL和Java代码分离维护起来也方便。我最初也是这么想的直到在一个快速迭代、需求频繁变动的内部工具项目中我被XML文件之间来回切换和繁琐的namespaceid匹配搞得有点烦躁才决定认真试试注解开发。几年用下来我的结论是MyBatis的注解开发绝不是为了取代XML而是一种强有力的补充和特定场景下的最优解。它特别适合那些SQL逻辑相对简单、变动频繁、或者你希望DAO层接口能“自成一体”、减少文件跳转的场合。比如管理后台的CRUD接口、简单的报表查询、或者是一些原型验证阶段的功能。当你看到一个接口方法同时就能看到它要执行的SQL这种“所见即所得”的体验在开发调试阶段效率提升非常明显。当然网上很多教程只告诉你注解怎么用却很少说清楚什么时候用、用了有什么坑。这篇内容我就结合自己趟过的路把MyBatis注解开发从入门到进阶再到生产环境下的混合使用策略掰开揉碎了讲清楚。我们会涵盖基础的CRUD、复杂的结果映射、动态SQL、以及二级缓存等核心主题目标就是让你看完后不仅能写出注解代码更能做出合适的技术选型。2. 环境搭建与基础CRUD注解实战开始写注解之前得先把场子搭起来。这里假设你已经在用Spring Boot整合MyBatis无非就是加依赖、配数据源。关键点在于要确保MyBatis能扫描到你的Mapper接口。2.1 核心依赖与配置要点在你的pom.xml里需要的是mybatis-spring-boot-starter。版本选择上我建议直接上较新的稳定版比如3.0.x以上。新版本对注解的支持更完善也修复了不少历史遗留问题。dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version3.0.3/version !-- 示例版本请使用最新稳定版 -- /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency在application.yml中基础的数据库配置必不可少。但关于MyBatis本身有一个配置项对注解开发至关重要mybatis: configuration: map-underscore-to-camel-case: true # 强烈建议开启下划线转驼峰省去大量Result映射开启这个配置后数据库字段user_name会自动映射到Java实体属性userName上对于简单的查询你甚至可以不写任何Result映射非常省事。这是很多新手会忽略的一个高效技巧。2.2 核心CRUD注解逐一看假设我们有一个User实体和对应的UserMapper接口。下面我们看最常用的四个注解。Select查询的基石Mapper public interface UserMapper { Select(SELECT id, user_name, age, email FROM user WHERE id #{id}) User selectById(Long id); Select(SELECT * FROM user WHERE age #{minAge}) ListUser selectByMinAge(Integer minAge); }注意SELECT *在注解里要谨慎使用。如果数据库表字段顺序或数量发生变化而你的实体类没及时更新可能会导致映射错误。显式列出字段是更稳妥的做法尤其是在生产环境。Insert插入数据与返回主键插入操作简单但如何获取数据库生成的主键比如自增ID是个关键点。Insert(INSERT INTO user (user_name, age, email) VALUES (#{userName}, #{age}, #{email})) Options(useGeneratedKeys true, keyProperty id) // 关键在这里 int insertUser(User user);Options注解的useGeneratedKeys true告诉MyBatis使用JDBC的getGeneratedKeys方法来获取数据库生成的主键。keyProperty id指定将这个值回填到参数对象user的id属性中。执行完这个方法后user.getId()就能拿到插入的ID了。Update 与 Delete更新与删除这两个注解相对直接。Update(UPDATE user SET email #{email} WHERE id #{id}) int updateEmailById(Param(id) Long id, Param(email) String email); Delete(DELETE FROM user WHERE id #{id}) int deleteById(Long id);这里引入了Param注解。当方法有多个参数时你必须使用Param给每个参数命名在SQL中通过#{参数名}来引用。如果只有一个参数且是基本类型/String可以不用Param但为了清晰我习惯都加上。2.3 关于Param注解的深度理解Param的作用不仅仅是解决多参数问题。它本质上是为参数创建了一个在SQL上下文中可用的名字。即使你只有一个复杂对象参数有时也需要它。// 场景模糊查询参数是一个User对象但我们只想用其中的name属性进行模糊匹配 Select(SELECT * FROM user WHERE user_name LIKE CONCAT(%, #{user.name}, %)) ListUser selectByUserCondition(Param(user) User user);如果没有Param(user)在SQL中直接写#{name}是取不到值的因为MyBatis不知道name属性属于哪个参数对象。通过Param指定后就可以用#{user.name}这种OGNL表达式来访问对象属性了。这是处理复杂查询条件时的一个实用模式。3. 解决复杂映射Results与ResultMap基础CRUD的SQL简单映射也简单。但遇到查询结果包含关联对象、集合或者字段名与属性名无法通过驼峰规则自动映射时就需要Results和ResultMap出场了。3.1 处理字段名不对应与简单关联假设我们查询用户及其所属部门假设部门信息在user表中有dept_id和dept_name字段但实体类中是deptId和deptName。Select(SELECT u.id, u.user_name, u.dept_id, d.name as dept_name FROM user u LEFT JOIN department d ON u.dept_id d.id WHERE u.id #{id}) Results({ Result(column id, property id, id true), // idtrue表示这是主键 Result(column user_name, property userName), Result(column dept_id, property deptId), Result(column dept_name, property deptName) }) User selectUserWithDeptById(Long id);Results注解可以理解为一个结果映射的集合。Result中的column是数据库查询结果的列名或别名property是Java实体类的属性名。当开启了map-underscore-to-camel-case后像user_name到userName的映射其实可以省略但这里为了演示完整性还是写了出来。对于主键建议明确标记id true这有助于提高性能尤其是在嵌套查询时。3.2 使用ResultMap复用映射规则如果同一个映射规则在多个Select方法中都要用到每次都写一遍Results太冗余了。这时可以用ResultMap。首先在一个方法上定义Results并指定一个唯一的idSelect(SELECT * FROM user WHERE id #{id}) Results(id userResultMap, value { Result(column id, property id, id true), Result(column user_name, property userName), Result(column dept_id, property deptId) }) User selectByIdForMap(Long id);然后在其他方法中通过ResultMap来引用这个映射规则Select(SELECT * FROM user WHERE age #{age}) ResultMap(userResultMap) // 直接复用上面定义的映射 ListUser selectByAge(Integer age);这种方式极大地减少了重复代码。但请注意ResultMap引用的id必须在同一个Mapper接口内定义。它无法跨Mapper接口引用这是注解开发的一个局限性。3.3 一对多、多对一关联映射的挑战与方案这是注解开发最棘手的部分之一。在XML中我们可以使用collection和association轻松定义复杂关联。在注解中MyBatis提供了One和Many注解来模拟但用起来颇为繁琐。例如查询用户及其所有订单一对多。// OrderMapper.java Mapper public interface OrderMapper { Select(SELECT * FROM order WHERE user_id #{userId}) ListOrder selectByUserId(Long userId); } // UserMapper.java Select(SELECT * FROM user WHERE id #{id}) Results({ Result(id true, column id, property id), Result(column user_name, property userName), Result(column id, property orderList, // 将用户id作为参数传递给另一个查询 many Many(select com.example.mapper.OrderMapper.selectByUserId)) }) User selectUserWithOrders(Long id);Many注解的select属性指定了另一个Mapper方法的全限定名或同一Mapper内的方法名。MyBatis会先执行主查询SELECT * FROM user然后对每一条结果再执行一次OrderMapper.selectByUserId(user.id)最后将查询到的ListOrder集合设置到User对象的orderList属性中。这种方式的优缺点非常明显优点逻辑清晰直接利用已有的Mapper方法符合SQL直观思维。缺点容易产生N1查询问题。如果主查询返回10个用户那么就会产生1主查询10查询订单11次数据库查询性能隐患巨大。对于数据量大的场景这是不可接受的。因此对于复杂的关联查询我个人的强烈建议是不要在注解里硬扛回归XML写一个联表查询才是正道。你可以用Select注解执行一个联表查询SQL然后通过Results手动映射每一个字段包括嵌套对象的字段但这会让Results变得极其庞大和难以维护。此时XML的清晰和强大就体现出来了。这也引出了我的核心观点注解与XML混合使用各取所长。4. 注解下的动态SQLProvider与

相关新闻

可制造性设计(DFM)核心挑战与全流程实践指南

可制造性设计(DFM)核心挑战与全流程实践指南

2026/8/4 3:48:07

1. 从“画得出来”到“造得出来”:可制造性设计的核心挑战在硬件产品开发领域,有一个让无数工程师和项目经理头疼不已的经典困境:实验室里功能完美、性能惊艳的样机,一旦进入量产阶段,要么良率惨不忍睹,要么…

终极免费网盘直链下载助手:八大平台高速下载完全指南

终极免费网盘直链下载助手:八大平台高速下载完全指南

2026/8/4 3:48:07

终极免费网盘直链下载助手:八大平台高速下载完全指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…

PICAXE编程进阶:从输入输出到项目实战的嵌入式系统开发指南

PICAXE编程进阶:从输入输出到项目实战的嵌入式系统开发指南

2026/8/4 3:48:07

1. 项目概述:从入门到实践,解锁PICAXE编程的核心技能上次我们聊了PICAXE编程的入门,搭建了环境,点亮了第一个LED,算是和这个小家伙打了个招呼。很多朋友反馈说,感觉像是刚拿到驾照,只会直行和倒…

实战电话号码定位解决方案:如何高效实现地理位置精准查询

实战电话号码定位解决方案:如何高效实现地理位置精准查询

2026/8/4 5:08:11

实战电话号码定位解决方案:如何高效实现地理位置精准查询 【免费下载链接】location-to-phone-number This a project to search a location of a specified phone number, and locate the map to the phone number location. 项目地址: https://gitcode.com/gh_m…

BepInEx 6.0跨平台架构解析:从插件加载到Harmony集成的Unity模组开发指南

BepInEx 6.0跨平台架构解析:从插件加载到Harmony集成的Unity模组开发指南

2026/8/4 5:08:11

1. 项目概述:为什么我们需要深入理解BepInEx 6.0如果你是一名Unity游戏模组开发者,或者你正在为某个Unity游戏开发插件,那么“BepInEx”这个名字对你来说一定不陌生。它几乎是当前Unity游戏社区插件生态的基石,从《英灵神殿》到《…

Java/PHP/Python运行时Hook技术与反Hook攻防实战

Java/PHP/Python运行时Hook技术与反Hook攻防实战

2026/8/4 5:08:11

1. 运行时Hook技术基础回顾在上一篇文章中,我们已经详细介绍了Java、PHP和Python三种语言的运行时Hook基本原理和常见实现方式。简单回顾一下,运行时Hook技术主要通过在程序执行过程中动态修改函数调用、方法实现或系统API调用,实现对程序行为…

打破壁垒,联防联控:构建军警民一体化的要地安保“共治底座”

打破壁垒,联防联控:构建军警民一体化的要地安保“共治底座”

2026/8/4 5:08:11

打破壁垒,联防联控:构建军警民一体化的要地安保“共治底座”一、建设背景与传统多方防控体系痛点党政核心枢纽、国防战备要地、城市重点商圈、重大活动场馆、交通能源核心设施等关键防护目标,是国家安全、社会稳定、民生运行的核心战略载体&a…

告别入门迷茫!4步拆解LLM Agent核心工程,速通大模型实战

告别入门迷茫!4步拆解LLM Agent核心工程,速通大模型实战

2026/8/4 5:08:11

想学LLM Agent的人,八成卡在第一关:网上的教程要么停在"写提示词",要么一上来甩你一堆框架名,看完更懵。 这其实不怪你。Agent工程的坑在于——它是一个层层叠加的东西,每个名词管的事都不一样。把层次拆开&…

3步彻底解决Mac NTFS读写难题:免费开源Nigate工具终极指南

3步彻底解决Mac NTFS读写难题:免费开源Nigate工具终极指南

2026/8/4 4:58:10

3步彻底解决Mac NTFS读写难题:免费开源Nigate工具终极指南 【免费下载链接】Free-NTFS-for-Mac Nigate: An open-source NTFS utility for Mac. It supports all Mac models (Intel and Apple Silicon), providing full read-write access, mounting, and managemen…

ncmdumpGUI:一键解锁网易云音乐ncm文件的终极解决方案

ncmdumpGUI:一键解锁网易云音乐ncm文件的终极解决方案

2026/8/3 4:49:52

ncmdumpGUI:一键解锁网易云音乐ncm文件的终极解决方案 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾经从网易云音乐下载了心爱的歌曲&am…

分布式配置中心选型实战:Nacos与Consul在创业场景下的对比

分布式配置中心选型实战:Nacos与Consul在创业场景下的对比

2026/8/3 19:24:18

分布式配置中心选型实战:Nacos与Consul在创业场景下的对比工程导读:本文深入讨论 分布式配置中心选型实战:Nacos与Consul在创业场景下的对比 在生产工程实践中的核心落地方案。基于 分布式架构与微服务设计 视角,剖析实际痛点、架…

MoneyPrinterPlus实战指南:AI视频批量生成与自动化发布完整解决方案

MoneyPrinterPlus实战指南:AI视频批量生成与自动化发布完整解决方案

2026/8/3 20:38:37

MoneyPrinterPlus实战指南:AI视频批量生成与自动化发布完整解决方案 【免费下载链接】MoneyPrinterPlus AI一键批量生成各类短视频,自动批量混剪短视频,自动把视频发布到抖音,快手,小红书,视频号上,赚钱从来没有这么容易过! 支持本地语音模型chatTTS,fasterwhisper,…

3步解决Windows DLL缺失问题:VisualCppRedist AIO终极运行库修复方案

3步解决Windows DLL缺失问题:VisualCppRedist AIO终极运行库修复方案

2026/8/4 0:07:58

3步解决Windows DLL缺失问题:VisualCppRedist AIO终极运行库修复方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经在打开游戏或软件时遇…

SingleFile终极指南:一键保存完整网页的5大核心功能

SingleFile终极指南:一键保存完整网页的5大核心功能

2026/8/4 0:07:58

SingleFile终极指南:一键保存完整网页的5大核心功能 【免费下载链接】SingleFile Web Extension for saving a faithful copy of a complete web page in a single HTML file 项目地址: https://gitcode.com/gh_mirrors/si/SingleFile 你是否曾经遇到过这样的…

国家中小学智慧教育平台电子课本下载终极方案:三步免费获取PDF教材

国家中小学智慧教育平台电子课本下载终极方案:三步免费获取PDF教材

2026/8/4 0:07:58

国家中小学智慧教育平台电子课本下载终极方案:三步免费获取PDF教材 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/2 17:06:42

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/3 7:25:44

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/3 2:41:27

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…