本文件把 MyBatis 知识整合为可落地的系统能力数据访问层架构、主线项目演进、模块边界、事务边界、多数据源、代码规范、专家清单和完整面试题答案。1. 五层能力模型层级能力目标入门能配置 MyBatis写 Mapper XML完成 CRUD进阶能写动态 SQL、ResultMap、TypeHandler、分页、测试高级能理解执行流程、缓存、插件、事务和性能优化精通能治理 SQL、批处理、多环境、迁移、可观测性专家能设计数据访问架构、多数据源、读写分离、分库分表边界2. 数据访问层架构推荐分层controller - application service / service - domain service - repository / mapper - databaseMyBatis Mapper 不应承担业务规则它只负责 SQL 和表映射。3. Mapper 与 Repository简单项目Service - Mapper复杂项目Service - Repository - MapperRepository 封装多个 Mapper、组装领域对象、隐藏数据库表结构。RepositorypublicclassCourseRepository{privatefinalCourseMappercourseMapper;privatefinalLessonMapperlessonMapper;publicCourseDetailfindDetail(LongcourseId){CourseDOcoursecourseMapper.selectById(courseId);ListLessonDOlessonslessonMapper.selectByCourseId(courseId);returnCourseDetailAssembler.toDomain(course,lessons);}}4. DO、DTO、Domain 分离UserCreateRequest - CreateUserCommand - User domain - UserDO - users table不要让数据库对象直接穿透到接口响应// 不推荐publicUserDOgetUser(Longid){returnuserMapper.selectById(id);}更好publicUserResponsegetUser(Longid){UseruseruserRepository.findById(id);returnUserResponse.from(user);}5. 主线项目Knowledge Hub业务背景用户注册和登录。课程管理。章节管理。学习进度。订单和支付记录。搜索和筛选。后台管理。报表统计。技术目标用 MyBatis 管理数据访问。动态 SQL 支持复杂查询。ResultMap 支持聚合对象。Service 管理事务。测试覆盖 Mapper。性能优化支持大数据量查询。架构支持未来多数据源和读写分离。6. Stage 1用户 CRUD表createtableusers(idbigintgeneratedbydefaultasidentityprimarykey,usernamevarchar(64)notnullunique,emailvarchar(128)notnull,statusvarchar(32)notnull,created_attimestampnotnull);MapperpublicinterfaceUserMapper{UserDOselectById(Longid);intinsert(UserDOuser);intupdateStatus(Param(id)Longid,Param(status)Stringstatus);}训练点Mapper XML。参数绑定。自增主键。基础事务。7. Stage 2课程搜索需求keyword。level。status。createdAt 范围。游标分页。QuerypublicrecordCourseSearchQuery(Stringkeyword,Stringlevel,Stringstatus,LonglastId,Integerlimit){}训练点where。if。动态分页。索引设计。8. Stage 3课程详情聚合课程详情包含course。lessons。teacher。statistics。策略单个详情页可使用 join ResultMap。大对象图可分多次查询组装。列表页避免一对多 join 破坏分页。9. Stage 4学习进度事务需求标记章节完成。更新课程进度。写学习日志。ServiceTransactionalpublicvoidcompleteLesson(LonguserId,LonglessonId){progressMapper.upsertLessonProgress(userId,lessonId);progressMapper.recalculateCourseProgress(userId,lessonId);learningLogMapper.insert(userId,lessonId,COMPLETE);}训练点事务边界。幂等更新。唯一索引。并发安全。10. Stage 5订单与库存需求创建订单。扣减库存。防超卖。写订单日志。SQLupdatecourse_stocksetstockstock-#{quantity}wherecourse_id#{courseId}andstock#{quantity}如果影响行数为 0说明库存不足。训练点乐观并发控制。事务。行锁。异常回滚。11. Stage 6报表统计需求每日新增用户。课程完成率。热门课程。策略小规模直接 SQL 聚合。中等规模加索引和预聚合表。大规模用数仓、OLAP 或搜索引擎。MyBatis 不应承担所有分析型查询压力。12. Stage 7多数据源与读写分离场景主库写。从库读。报表库。租户库。风险主从延迟。事务一致性。数据源路由错误。跨库事务复杂。专家实践事务内强制主库。写后读走主库或等待同步。路由逻辑集中。业务层不直接拼数据源。13. Stage 8分库分表边界MyBatis 本身不是分库分表框架。可结合ShardingSphere。数据库中间件。应用层路由。分库分表前先确认单表数据量是否真的成为瓶颈。索引和归档是否已优化。查询维度是否稳定。跨分片查询如何处理。分布式事务是否可避免。14. SQL 规范建议Mapper 方法名表达业务查询意图。禁止${}拼接用户输入。动态 SQL 不写复杂业务规则。查询必须明确列名避免select *。大列表必须分页。更新必须带明确 where。重要 SQL 必须有测试。慢 SQL 必须 explain。15. 目录规范src/main/java/com/example/knowledge/ ├── user/ │ ├── controller/ │ ├── service/ │ ├── domain/ │ ├── repository/ │ └── mapper/ ├── course/ ├── order/ └── shared/ src/main/resources/mapper/ ├── user/ ├── course/ └── order/按业务模块组织避免所有 Mapper 堆在一个目录。16. 专家架构检查清单数据访问Mapper 是否只负责 SQLService 是否控制事务是否避免 Controller 直接调 Mapper是否有 Repository 隔离复杂组装SQL是否有注入风险是否有 N1是否分页是否有索引是否 explain事务边界是否正确是否有自调用失效是否捕获异常导致不回滚是否存在长事务性能是否深分页是否返回过多列是否批处理过大是否连接池配置合理工程Mapper 测试是否覆盖关键 SQL数据库迁移是否版本化SQL 日志是否脱敏慢 SQL 是否可观测17. MyBatis 反模式Controller 直接调用 Mapper。XML 中写复杂业务规则。${}拼接用户输入。所有查询都select *。列表页使用嵌套 select。不写 Mapper 测试。生产库手工改表。大事务包住远程调用。分页不考虑深分页。二级缓存无失效策略。Mapper 返回 Map 贯穿业务层。数据库对象直接暴露给 API。18. 面试题完整答案18.1 MyBatis 适合什么架构位置MyBatis 适合放在数据访问层负责 SQL 执行和数据库表映射。它不应承担业务规则、事务编排或接口响应组装。复杂项目中可在 Mapper 外增加 Repository隔离表结构和领域模型。18.2 为什么 Controller 不应该直接调用 MapperController 负责 HTTP 协议和入参出参不应知道数据库访问细节。直接调用 Mapper 会让事务、业务规则、权限和数据组装散落在接口层难以复用和测试。应由 Service 或 Application Service 组织业务流程。18.3 Repository 和 Mapper 有什么区别Mapper 是 MyBatis 的 SQL 映射接口通常对应表或 SQL。Repository 是领域层或应用层的数据访问抽象可组合多个 Mapper隐藏数据库表结构返回领域对象。简单项目可省略 Repository复杂项目建议引入。18.4 MyBatis 项目如何避免 SQL 混乱建立 SQL 规范按业务模块组织 Mapper方法命名表达意图动态 SQL 控制复杂度重要 SQL 有测试禁止不安全${}统一分页和排序白名单慢 SQL 进入审查流程。18.5 如何设计事务边界事务边界应围绕一个业务用例例如创建订单、完成课程、退款。事务内只放必要数据库操作避免远程调用和长时间计算。事务应放 Service 层并明确回滚异常。18.6 多数据源如何治理数据源路由应集中处理业务代码不应到处手动选择数据源。事务内必须明确数据源读写分离要处理主从延迟写后读要走主库或有一致性策略。跨库事务应尽量通过业务设计避免。18.7 分库分表前要考虑什么先确认瓶颈是否真的来自单库单表。要评估索引、归档、缓存、读写分离是否已足够。分片键要稳定跨分片查询、分页、事务、唯一 ID、数据迁移和运维成本都必须提前设计。18.8 如何判断一个 MyBatis 开发者达到专家水平不仅能写 CRUD还能理解执行链路、动态 SQL、ResultMap、缓存、事务、插件、性能、安全和架构边界。专家能设计数据访问规范定位慢 SQL治理事务和多数据源并为未来扩展留下迁移路径。19. 终极知识点总表基础SqlSessionFactory。SqlSession。Mapper。Mapper XML。#{}/${}。CRUD。进阶Dynamic SQL。ResultMap。association。collection。TypeHandler。Spring Boot Starter。Transaction。高级Executor。MappedStatement。BoundSql。ParameterHandler。ResultSetHandler。Cache。Plugin。精通Batch。Pagination。Testcontainers。Flyway。SQL explain。Connection Pool。Observability。专家Repository。多数据源。读写分离。分库分表。缓存一致性。数据访问治理。SQL 安全审计。20. 项目演进路线扩展20.1 v1 单体 CRUD能力用户、课程、章节基础表。Mapper XML CRUD。Service 事务。H2 本地测试。重点不是功能多而是建立规范。20.2 v2 复杂查询能力课程搜索。多条件筛选。游标分页。课程卡片 DTO。Mapper 测试覆盖动态 SQL。20.3 v3 聚合详情能力课程详情。章节列表。讲师信息。学习统计。架构选择简单详情可 ResultMap join。复杂详情用 Repository 多次查询组装。20.4 v4 事务用例能力报名课程。扣减库存。写学习进度。写审计日志。重点幂等。乐观锁。唯一约束。事务回滚。20.5 v5 性能治理能力慢 SQL 日志。explain 审查。索引优化。N1 消除。连接池监控。20.6 v6 架构升级能力Repository。多数据源。读写分离。缓存层。数据迁移。ADR。21. 数据访问层 ADR 示例# ADR: 课程详情使用 Repository 组装而不是深层 ResultMap ## 背景 课程详情包含课程、章节、讲师、统计数据。单条 join SQL 行数膨胀ResultMap 复杂。 ## 决策 使用 CourseRepository 分别调用 CourseMapper、LessonMapper、TeacherMapper、StatisticMapper然后组装 CourseDetail。 ## 后果 优点SQL 简单、可测试、易优化。 代价需要额外组装代码并注意批量查询避免 N1。22. 团队 SQL Review 清单是否使用#{}绑定业务值是否存在${}是否白名单是否明确列名where 条件是否完整update/delete 是否可能全表是否有合适索引是否有深分页是否有 N1是否返回过多数据是否有 Mapper 测试是否需要 explain23. 专家场景题23.1 课程搜索越来越慢怎么办先看 SQL 日志和 explain确认是否索引失效、like 前缀通配、排序 filesort、返回数据过多。短期可加索引、改游标分页、减少列。中期可预计算热字段。若搜索复杂度高考虑 Elasticsearch/OpenSearch而不是继续用 MyBatis 承担全文搜索。23.2 学习进度并发更新如何保证正确使用唯一约束保证幂等如(user_id, lesson_id)唯一。完成操作可 upsert。课程进度更新可基于数据库聚合重新计算或使用乐观锁版本号。事务内保持更新顺序一致避免死锁。23.3 多租户如何设计简单场景可每张表加tenant_id并在所有查询中显式过滤。复杂场景可使用 schema/db 隔离。插件可做兜底但不能替代 SQL 规范和测试。必须防止跨租户访问服务端权限和数据条件都要校验。24. 架构专家题补充答案24.1 MyBatis 项目什么时候需要 Repository当单个业务查询需要组合多个 Mapper、隐藏表结构、返回领域对象、隔离 DO 和 Domain 时需要 Repository。简单 CRUD 可直接 Service 调 Mapper但复杂业务中 Repository 能降低 Service 对数据库结构的耦合。24.2 MyBatis 能否用于领域驱动设计可以但不要让 Mapper 直接成为领域模型的一部分。Mapper 属于基础设施层Repository 负责把数据库对象转换为领域对象。领域层不应依赖 MyBatis API 或 XML。24.3 如何让 MyBatis 系统可持续演进建立 SQL 规范、Mapper 测试、数据库迁移、性能监控、慢 SQL 审查、分层架构和 ADR。随着复杂度上升引入 Repository、缓存层、多数据源治理和读写分离但不要过早复杂化。25. 终极专家检查清单基础Mapper namespace 正确。参数命名清晰。XML 被扫描。#{}使用正确。动态 SQL空条件安全。空集合安全。排序白名单。OGNL 简单。映射ResultMap 有 id。列别名清晰。一对多分页安全。TypeHandler 无副作用。事务Service 控制边界。无自调用失效。异常回滚明确。无长事务。性能SQL explain。索引匹配。无 N1。无深分页。连接池合理。安全无 SQL 注入。日志脱敏。权限在服务端。多租户隔离。架构DO/DTO/Domain 分离。Mapper 不承载业务。Repository 边界清晰。多数据源集中治理。数据迁移版本化。