"小崔,注解不是来取代XML的,是来解放你的。简单CRUD写注解,复杂映射留XML,这叫各得其所。"——白歌
本章定位
一句话:本章解决"如何不用XML、直接在Java接口上通过注解完成SQL映射,以及注解与XML如何取舍"的问题。
飞翔科技的微服务拆分后,小崔发现很多服务只有简单的单表CRUD,却还要维护一堆XML文件。白歌提议:新服务的简单Mapper全部用注解,老服务的复杂关联查询保留XML。这一章,小崔把MyBatis的注解全家桶学透,并建立"注解 vs XML"的决策框架。
学习路线图
学习顺序说明:
- 先学四大CRUD注解(@Select / @Insert / @Update / @Delete)→ 注解的"Hello World"
- 再学结果映射注解(@Results / @Result / @One / @Many)→ 注解版的resultMap和association/collection
- 再学辅助注解(@Param / @Options / @SelectKey)→ 参数命名、选项配置、主键回写
- 最后看动态SQL注解(@SelectProvider)→ 注解场景下的动态SQL解决方案
文件关系说明
| 文件 | 一句话角色 |
|---|---|
Select.md | 查询注解:@Select替代<select>,直接在接口方法上写SQL |
Insert.md | 插入注解:@Insert替代<insert>,配合@Options或@SelectKey获取自增ID |
Update.md | 更新注解:@Update替代<update>,适合单表全量/增量更新 |
Delete.md | 删除注解:@Delete替代<delete>,简单删除的标准写法 |
Results.md | 结果映射容器:@Results替代<resultMap>,内部嵌套多个@Result |
Result.md | 单列映射项:@Result替代<id>/<result>,声明列与属性的对应关系 |
One.md | 一对一注解:@One替代<association>,指定嵌套查询或嵌套结果 |
Many.md | 一对多注解:@Many替代<collection>,指定嵌套查询或嵌套结果 |
Param.md | 参数命名注解:@Param替代XML中的参数名推断,多参数场景必备 |
Options.md | 选项配置注解:@Options替代<insert>的属性(useGeneratedKeys、timeout等) |
SelectKey.md | 主键回写注解:@SelectKey替代<selectKey>,插入前/后查询主键 |
SelectProvider.md | 动态SQL注解:@SelectProvider等Provider系列,通过Java类动态生成SQL |
知识图谱
XML标签 ↔ 注解对照表:
| XML标签 | 注解 | 适用场景 |
|---|---|---|
<select> | @Select | 简单查询,SQL短且固定 |
<insert> | @Insert | 单表插入,配合@Options获取自增ID |
<update> | @Update | 单表更新,字段少、条件简单 |
<delete> | @Delete | 单条/批量删除 |
<resultMap> | @Results + @Result | 列名与属性名不一致,但嵌套不深 |
<association> | @One | 一对一关联,SQL简单 |
<collection> | @Many | 一对多关联,数据量小 |
<selectKey> | @SelectKey | 非自增主键(如UUID、序列)回写 |
<sql> | 无直接等价 | 注解不支持SQL片段复用,复杂复用场景回XML |
<if>/<where> | @SelectProvider | 动态SQL,通过Provider类用Java代码拼接 |
什么时候用XML,什么时候用注解?
| 场景 | 推荐方式 | 理由 |
|---|---|---|
| 简单单表CRUD | 注解 | 代码内聚,减少文件数量,维护成本低 |
| 复杂动态SQL(多条件) | XML | <if>/<where>/<foreach> 比Provider类可读性高 |
| 复杂resultMap(多层嵌套) | XML | XML的层级结构比@Results嵌套更清晰 |
| SQL片段复用 | XML | <sql>标签支持全局复用,注解无此机制 |
| 需要DBA审核SQL | XML | SQL集中管理,便于版本控制和审计 |
| 快速原型/微服务 | 注解 | 开发速度快,适合简单服务的快速迭代 |
与下一章的衔接
本章学完后,小崔能用注解快速开发简单Mapper,但生产环境用户量一上来,同样的查询每秒执行几百次,数据库压力剧增。李眉的监控告警开始响。
下一章《缓存与性能优化》将解决:MyBatis的一级缓存(SqlSession级)和二级缓存(Mapper级)如何工作、怎么配置、什么时候该用自定义缓存(Redis/Ehcache),以及分页插件和Executor执行器的选择策略。
"注解让你写得快,缓存让你跑得快。两个快加起来,才是能上线的代码。"——大翔