整理自 MyBatis 面试题 37 道。持久层专题:JDBC → MyBatis / Hibernate → MyBatis-Plus 概述。
相关学习笔记
| 专题 | 笔记 |
|---|---|
| JDBC | JDBC 概述 · CRUD 实战 |
| MyBatis 概述 | MyBatis 概述 |
| Mapper 与 XML | 环境与 Mapper · 动态 SQL |
| Hibernate | Hibernate 概述 · CRUD 实战 |
| MyBatis-Plus | MyBatis-Plus 概述 · 条件与分页 |
| Spring Boot 集成 | Spring Boot Web 与运维 |
目录
简介与选型
1. MyBatis 是什么
半 ORM 框架:封装 JDBC,开发者编写 SQL,通过 XML/注解映射 POJO 与表记录,灵活控制 SQL 性能。
2. 优缺点
| 优点 | 缺点 |
|---|---|
| SQL 与代码解耦、动态 SQL、减少 JDBC 样板代码 | SQL 工作量大,依赖开发者 SQL 功底 |
| 易与 Spring 集成、多数据库兼容(走 JDBC) | SQL 绑定具体库,移植性弱于纯 ORM |
3. Hibernate 与 MyBatis 区别
| 维度 | MyBatis | Hibernate |
|---|---|---|
| 映射 | 半自动,SQL 手写,多表配置简单 | 全自动表映射,多表复杂 |
| SQL | 手写、易优化,库无关性弱 | HQL、缓存、级联强,换库方便 |
| 场景 | 互联网、性能敏感、需求多变 | 需求稳定、中小型 OA 等 |
4. 为何称半自动 ORM
关联对象/集合需手写 SQL;Hibernate 可按对象关系模型直接加载关联,全自动。
5. 传统 JDBC 的问题
连接频繁创建释放、SQL 硬编码难维护、参数与结果集映射重复。
6. MyBatis 如何解决 JDBC 不足
连接池(mybatis-config.xml)、SQL 放 mapper.xml、自动参数与结果映射到 Java 对象。
7. 适用场景
MyBatis 专注 SQL,适合性能要求高、SQL 需精细控制的项目;Hibernate 适合需求相对稳定、希望少写 SQL 的场景。
架构与执行
8. 编程步骤
SqlSessionFactory → SqlSession → 执行 SQL → commit / close。
9. 工作原理(简述)
读配置 → 加载映射文件 → 构建 SqlSessionFactory → SqlSession → Executor 执行 MappedStatement → 参数映射 → 结果映射。
10. 功能架构三层
API 接口层、数据处理层(SQL 查找/解析/执行/映射)、基础支撑层(连接、事务、配置、缓存)。
11. 框架设计
配置解析为 Configuration → SQL 解析得最终 SQL 与参数 → 执行 → 按映射转 HashMap/POJO 返回。
12. 什么是 DBMS
数据库管理系统,提供 DDL/DML,统一管理与访问数据库。
13. 为什么需要预编译
PreparedStatement 预编译可优化执行、复用计划;防 SQL 注入。MyBatis 默认对 SQL 预编译。
14. Executor 三种执行器
| 类型 | 说明 |
|---|---|
| Simple | 每次新建 Statement,用完即关 |
| Reuse | 以 SQL 为 key 复用 Statement |
| Batch | 批量 addBatch / executeBatch |
作用域在 SqlSession 生命周期内。
15. 如何指定 Executor
settings 中 defaultExecutorType,或 openSession(ExecutorType.BATCH)。
16. 延迟加载
支持 association / collection;lazyLoadingEnabled=true;CGLIB 代理,调用 getter 时再发 SQL 查关联对象。
映射器与 SQL
17. #{} 与 ${} 区别
#{} | ${} | |
|---|---|---|
| 处理 | 占位符,预编译 ? | 字符串拼接 |
| 安全 | 防注入 | 有注入风险 |
| 替换时机 | DBMS 内 | DBMS 外 |
18. 模糊查询 like 写法
推荐 CONCAT('%', #{name}, '%');或 "%"#{name}"%"(注意双引号);避免 '%${name}%'。
19. Mapper 多参数传递
@Param(推荐)、Map、JavaBean、顺序 #{}(不推荐)。
20. 批量操作
<foreach> 拼 VALUES (...),(...);或 ExecutorType.BATCH(注意自增 id 在 commit 前可能拿不到)。
21. 获取自增主键
<insert useGeneratedKeys="true" keyProperty="id">。
22. 属性名与列名不一致
SQL 别名,或 <resultMap> 映射。
23. Mapper 编写方式
实现类继承 SqlSessionDaoSupport、MapperFactoryBean、MapperScannerConfigurer(最常用)。
24. 接口绑定
接口方法与 SQL 绑定:注解(@Select 等)或 XML namespace = 接口全限定名。
25. Mapper 接口调用要求
方法名 = statement id;parameterType / resultType 一致;namespace = 接口路径。
26. Dao 接口原理
JDK 动态代理 → MappedStatement 执行 SQL;方法不能重载(全限定名+方法名唯一)。
27. 不同 XML 中 id 能否重复
有 namespace 可重复;无 namespace 不可(namespace+id 为 Map key)。
28. Xml 与内部结构映射
解析进 Configuration:<parameterMap>、<resultMap>、<select|insert|update|delete> → MappedStatement / BoundSql。
29. 结果封装形式
<resultMap> 逐字段映射;或列别名 AS 与属性名一致,反射赋值。
30. Xml 中常见标签
resultMap、parameterMap、sql、include、selectKey;动态 SQL:if、where、set、foreach、choose、trim、bind 等。
31. include 引用顺序
被引用的 <sql> 可写在后面;未解析完会标记延后二次解析。
→ 环境与 Mapper · 动态 SQL
关联与高级特性
32. 一对多 / 一对一查询
支持;方式:单独 SQL、嵌套查询(N+1 注意)、JOIN 一次查出再映射。
33. 枚举映射
自定义 TypeHandler,实现 setParameter / getResult。
34. 动态 SQL
OGNL 计算表达式,动态拼接;标签见第 30 题。
35. 分页
RowBounds 内存分页;或 SQL 物理分页;分页插件拦截 SQL 重写并加 limit(如 PageHelper)。
36. 插件原理
仅可拦截 ParameterHandler、ResultSetHandler、StatementHandler、Executor;JDK 动态代理 + Interceptor.intercept()。
37. 一级、二级缓存
| 级别 | 作用域 | 默认 |
|---|---|---|
| 一级 | SqlSession | 开启 |
| 二级 | Mapper namespace | 关闭,需 <cache/> 且实体可序列化 |
同一作用域内发生增删改会清空该作用域下 select 缓存。
MyBatis-Plus 面试补充
ORM 增强层:在 MyBatis 之上提供 BaseMapper、条件构造器、分页、代码生成等,不替代 XML 复杂 SQL。详见 MyBatis-Plus 环境与 BaseMapper。