1. 为什么需要整理MyBatis面试题?
最近帮团队面试了几位Java后端开发,发现很多候选人对MyBatis的理解停留在"会用"层面。问到动态SQL就只记得<if>标签,提到二级缓存就支支吾吾。这让我意识到,系统整理MyBatis核心知识点非常必要。
MyBatis作为Java生态中最主流的ORM框架之一,在中小型项目中应用广泛。根据2023年JetBrains开发者调查报告,超过62%的Java项目在使用MyBatis或它的增强版MyBatis-Plus。但很多开发者只是通过Spring Boot Starter简单集成,对底层机制一知半解。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. MyBatis核心机制解析
2.1 会话工厂与执行器体系
SqlSessionFactoryBuilder通过XML或Java Config构建SqlSessionFactory时,实际创建的是DefaultSqlSessionFactory实例。这里有个容易忽略的细节:配置文件中的<environments>标签可以定义多个环境,但最终只会根据default属性激活一个环境。
java复制String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
执行器(Executor)才是真正的SQL执行核心。面试常问的三种执行器区别:
- SimpleExecutor:每次执行都会创建新Statement
- ReuseExecutor:复用预处理Statement
- BatchExecutor:批量操作专用
实际项目中,ReuseExecutor在多数场景下性能最好。但要注意长时间不用的Statement需要手动清理。
2.2 动态SQL实现原理
MyBatis的动态SQL不是在运行时拼接字符串,而是通过OGNL表达式在XML解析阶段生成不同的SQL模板。比如这个典型的多条件查询:
xml复制<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
会被解析为带条件判断的SQL模板对象。面试官常会追问:"#{}和${}有什么区别?" 关键点:
#{}使用预编译占位符,防止SQL注入${}直接文本替换,适合动态表名等场景
2.3 插件开发与拦截原理
MyBatis的插件基于责任链模式实现。自定义插件需要实现Interceptor接口:
java复制@Intercepts({
@Signature(type= Executor.class,
method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MyPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置处理
Object result = invocation.proceed();
// 后置处理
return result;
}
}
常见应用场景:
- SQ
