外观
一句话答案
一级缓存 SqlSession 级别默认开启,二级缓存 Mapper 级别需手动开启,分布式环境建议关闭或用 Redis 替代。
核心要点
MyBatis 的核心功能:
- SQL 与代码分离:SQL 写在 XML 或注解中,Java 代码只调用接口方法
- 动态 SQL:
<if>,<foreach>,<choose>等标签,根据条件拼接 SQL - 结果映射(ResultMap):将 ResultSet 自动映射为 Java 对象(支持复杂嵌套关系)
- 一级缓存(SqlSession)/ 二级缓存(Mapper)
MyBatis 的 Mapper 接口代理实现:
@Mapper接口没有实现类,由 MyBatis 通过 JDK 动态代理生成代理对象- 调用 Mapper 方法 → 代理对象拦截 → 根据方法名和 namespace 找到对应 SQL → 执行
MyBatis 的插件机制(Interceptor/切面):
MyBatis 允许在以下四个核心对象的指定方法上插入拦截器:
java
Executor → update/query/commit/rollback(执行层)
StatementHandler → prepare/query/update(SQL 处理层)
ParameterHandler → setParameters(参数处理)
ResultSetHandler → handleResultSets(结果处理)典型插件应用:
java
// 分页插件(PageHelper/MyBatis-Plus):拦截 Executor.query(),在 SQL 后追加 LIMIT
// 数据权限:拦截 query,在 WHERE 子句追加权限过滤条件(如 AND dept_id = :deptId)
// SQL 日志打印:拦截 StatementHandler,打印完整的带参数 SQL
// 数据脱敏:拦截 ResultSetHandler,对返回结果的敏感字段做脱敏处理
@Intercepts({@Signature(type=Executor.class, method="query", args={...})})
public class MyPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置处理
Object result = invocation.proceed(); // 执行原方法
// 后置处理
return result;
}
}追问与易错
追问方向:
- 一级缓存什么时候失效?
- 二级缓存的脏数据问题?
- 生产推荐开启二级缓存吗?
易错点:
- ❌ MyBatis 缓存等于 Redis 缓存——是 JVM 级别的
- ❌ 二级缓存跨 namespace 生效——只在同一 namespace
💡 记忆锚点
一级缓存 = 个人笔记本(SqlSession级别,默认开,关了就没了),二级缓存 = 班级共享笔记(Mapper级别,要手动开)。分布式环境共享笔记会过时(脏数据),建议用Redis替代。Mapper接口没有实现类,全靠JDK动态代理撑场面。