Organized 50 interview questions into 12 categories: - 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc. - 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理 - 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc. - 04-消息队列 (1 file): RocketMQ/Kafka - 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc. - 06-JVM (1 file): JVM和垃圾回收 - 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc. - 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮 - 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化 - 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx - 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性 - 12-面试技巧 (1 file): 面试技巧和职业规划 All files renamed to Chinese for better accessibility and organized into categorized folders for easier navigation. Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
3.6 KiB
3.6 KiB
MyBatis 核心原理
问题
- MyBatis 的核心组件有哪些?
- MyBatis 的缓存机制(一级缓存、二级缓存)?
- MyBatis 的插件原理是什么?
- #{} 和 ${} 的区别是什么?
- MyBatis 如何处理批量操作?
- MyBatis 的动态 SQL 是如何实现的?
标准答案
1. MyBatis 核心组件
Configuration(全局配置)
↓
SqlSession(会话)
↓
Executor(执行器)
↓
StatementHandler(语句处理器)
↓
ParameterHandler(参数处理器)
↓
ResultSetHandler(结果集处理器)
2. 缓存机制
一级缓存(SqlSession 级别):
SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUser", 1);
User user2 = session.selectOne("selectUser", 1); // 从缓存获取
二级缓存(Mapper 级别):
<!-- 开启二级缓存 -->
<cache/>
User user1 = session1.selectOne("selectUser", 1);
session1.close(); // 一级缓存清空,写入二级缓存
User user2 = session2.selectOne("selectUser", 1); // 从二级缓存获取
3. 插件原理
拦截的四大组件:
- Executor
- StatementHandler
- ParameterHandler
- ResultSetHandler
示例:
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class SqlInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置逻辑
Object result = invocation.proceed();
// 后置逻辑
return result;
}
}
4. #{} vs $
| 特性 | #{} | ${} |
|---|---|---|
| 预处理 | 是(PreparedStatement) | 否(Statement) |
| SQL 注入 | 安全 | 不安全 |
| 类型转换 | 自动 | 需手动 |
| 动态表名/列名 | 不支持 | 支持 |
示例:
<!-- ✅ 安全 -->
SELECT * FROM users WHERE id = #{id}
<!-- ❌ SQL 注入风险 -->
SELECT * FROM users WHERE id = ${id}
<!-- ✅ 动态表名(只能用 ${})-->
SELECT * FROM ${tableName} WHERE id = #{id}
5. 批量操作
方式 1:SqlSession 批量:
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
UserMapper mapper = session.getMapper(UserMapper.class);
for (User user : users) {
mapper.insert(user);
}
session.commit();
} finally {
session.close();
}
方式 2:Batch Insert:
<insert id="batchInsert">
INSERT INTO users (name, email) VALUES
<foreach collection="users" item="user" separator=",">
(#{user.name}, #{user.email})
</foreach>
</insert>
6. 动态 SQL
常用标签:
<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
<select id="findUsersByIds" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
7. 阿里 P7 加分项
深度理解:
- 理解 MyBatis 的代理机制(MapperProxy)
- 理解二级缓存的并发问题
- 理解插件的责任链模式
实战经验:
- 有处理 MyBatis 性能问题的经验
- 有自定义插件的经验
- 有 MyBatis 与 Spring 集成的经验
架构能力:
- 能设计多数据源方案
- 能设计分库分表的 MyBatis 方案
- 能设计 MyBatis 监控体系