Files
interview/questions/02-数据库/MyBatis核心原理.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
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>
2026-03-01 00:10:53 +08:00

3.6 KiB
Raw Permalink Blame History

MyBatis 核心原理

问题

  1. MyBatis 的核心组件有哪些?
  2. MyBatis 的缓存机制(一级缓存、二级缓存)?
  3. MyBatis 的插件原理是什么?
  4. #{} 和 ${} 的区别是什么?
  5. MyBatis 如何处理批量操作?
  6. 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. 批量操作

方式 1SqlSession 批量

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();
}

方式 2Batch 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 监控体系