# MyBatis 核心原理
## 问题
1. MyBatis 的核心组件有哪些?
2. MyBatis 的缓存机制(一级缓存、二级缓存)?
3. MyBatis 的插件原理是什么?
4. #{} 和 ${} 的区别是什么?
5. MyBatis 如何处理批量操作?
6. MyBatis 的动态 SQL 是如何实现的?
---
## 标准答案
### 1. MyBatis 核心组件
```
Configuration(全局配置)
↓
SqlSession(会话)
↓
Executor(执行器)
↓
StatementHandler(语句处理器)
↓
ParameterHandler(参数处理器)
↓
ResultSetHandler(结果集处理器)
```
---
### 2. 缓存机制
**一级缓存(SqlSession 级别)**:
```java
SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUser", 1);
User user2 = session.selectOne("selectUser", 1); // 从缓存获取
```
**二级缓存(Mapper 级别)**:
```xml
```
```java
User user1 = session1.selectOne("selectUser", 1);
session1.close(); // 一级缓存清空,写入二级缓存
User user2 = session2.selectOne("selectUser", 1); // 从二级缓存获取
```
---
### 3. 插件原理
**拦截的四大组件**:
- Executor
- StatementHandler
- ParameterHandler
- ResultSetHandler
**示例**:
```java
@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 注入** | 安全 | 不安全 |
| **类型转换** | 自动 | 需手动 |
| **动态表名/列名** | 不支持 | 支持 |
**示例**:
```xml
SELECT * FROM users WHERE id = #{id}
SELECT * FROM users WHERE id = ${id}
SELECT * FROM ${tableName} WHERE id = #{id}
```
---
### 5. 批量操作
**方式 1:SqlSession 批量**:
```java
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**:
```xml
INSERT INTO users (name, email) VALUES
(#{user.name}, #{user.email})
```
---
### 6. 动态 SQL
**常用标签**:
```xml
```
---
### 7. 阿里 P7 加分项
**深度理解**:
- 理解 MyBatis 的代理机制(MapperProxy)
- 理解二级缓存的并发问题
- 理解插件的责任链模式
**实战经验**:
- 有处理 MyBatis 性能问题的经验
- 有自定义插件的经验
- 有 MyBatis 与 Spring 集成的经验
**架构能力**:
- 能设计多数据源方案
- 能设计分库分表的 MyBatis 方案
- 能设计 MyBatis 监控体系