# 2021最新版Mybatis面試題有哪些
## 一、MyBatis基礎篇
### 1. 什么是MyBatis?
MyBatis是一款優秀的**持久層框架**,它支持定制化SQL、存儲過程以及高級映射。MyBatis避免了幾乎所有的JDBC代碼和手動設置參數以及獲取結果集的工作,可以通過簡單的XML或注解來配置和映射原生信息,將接口和Java的POJO映射成數據庫中的記錄。
**核心特點**:
- 簡化JDBC操作
- 支持動態SQL
- 提供映射標簽
- 提供ORM功能
### 2. MyBatis的核心組件有哪些?
| 組件名稱 | 作用說明 |
|------------------|--------------------------------------------------------------------------|
| SqlSessionFactory | 創建SqlSession的工廠類,線程安全 |
| SqlSession | 執行持久化操作的核心接口,非線程安全 |
| Executor | 執行器,負責SQL語句生成和查詢緩存維護 |
| MappedStatement | 封裝了SQL語句的輸入/輸出參數等信息 |
| StatementHandler | 處理JDBC的Statement操作 |
### 3. #{}和${}的區別是什么?
```java
// #{}示例(預編譯)
@Select("SELECT * FROM user WHERE id = #{id}")
User getUserById(@Param("id") int id);
// ${}示例(直接拼接)
@Select("SELECT * FROM ${tableName} WHERE name = '${name}'")
List<User> getUsersByName(@Param("tableName") String table, @Param("name") String name);
區別對比:
特性 | #{} | ${} |
---|---|---|
處理方式 | 預編譯處理 | 字符串替換 |
安全性 | 防止SQL注入 | 存在SQL注入風險 |
參數類型 | 支持任意類型 | 通常需要字符串 |
適用場景 | WHERE條件/INSERT值 | 表名/列名等動態替換 |
一級緩存(本地緩存): - 作用范圍:SqlSession級別 - 默認開啟,同一個SqlSession中多次查詢會命中緩存 - 失效場景: - 執行增刪改操作(即使修改不同表) - 手動調用clearCache() - 執行commit()/rollback()
二級緩存(全局緩存):
<!-- 開啟二級緩存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- Mapper.xml中配置 -->
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
對比維度 | 一級緩存 | 二級緩存 |
---|---|---|
作用范圍 | SqlSession | Mapper(Namespace)級別 |
存儲結構 | 內存 | 可配置第三方緩存 |
開啟方式 | 默認開啟 | 需顯式配置 |
共享性 | 不能跨Session共享 | 跨SqlSession共享 |
主要元素:
<!-- if條件判斷 -->
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
</select>
<!-- choose/when/otherwise -->
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null">
AND author_name like #{author}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
<!-- foreach遍歷 -->
<insert id="insertUsers" parameterType="list">
INSERT INTO user(name, age) VALUES
<foreach item="item" collection="list" separator=",">
(#{item.name}, #{item.age})
</foreach>
</insert>
動態SQL方法對比:
1. if
:條件判斷
2. choose/when/otherwise
:類似Java的switch-case
3. trim/where/set
:處理SQL片段
4. foreach
:集合遍歷
5. bind
:創建變量并綁定到上下文
攔截器接口:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
實現分頁插件示例:
@Intercepts({
@Signature(type= Executor.class, method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class PageInterceptor implements Interceptor {
// 實現分頁邏輯...
}
插件開發步驟: 1. 實現Interceptor接口 2. 使用@Intercepts注解指定攔截方法 3. 在MyBatis配置文件中注冊插件
<plugins>
<plugin interceptor="com.example.PageInterceptor">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
1. 嵌套結果映射:
<resultMap id="blogResultMap" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="name" column="author_name"/>
</association>
</resultMap>
2. 嵌套查詢(N+1問題):
<resultMap id="blogResultMap" type="Blog">
<association property="author" column="author_id"
javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectAuthor" resultType="Author">
SELECT * FROM author WHERE id = #{id}
</select>
3. 集合映射:
<resultMap id="blogWithPostsMap" type="Blog">
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
</collection>
</resultMap>
配置加載階段:
SQL執行階段:
graph TD
A[SqlSessionFactory] --> B[創建SqlSession]
B --> C[獲取MapperProxy]
C --> D[創建MappedStatement]
D --> E[Executor執行]
E --> F[StatementHandler處理]
F --> G[ParameterHandler設置參數]
G --> H[ResultSetHandler處理結果]
核心對象生命周期:
防御機制: 1. 預編譯機制(#{}方式): - 使用PreparedStatement - 參數值會被安全處理
危險字符過濾:
// 在SqlSourceBuilder中處理參數
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(...);
// 對特殊字符進行轉義處理
}
XML特殊字符轉義:
<!-- 會自動轉義 <>等特殊字符 -->
<select id="safeQuery">
SELECT * FROM user WHERE name = #{name}
</select>
問題1:模糊查詢的正確寫法
// 正確方式(安全)
@Select("SELECT * FROM user WHERE name LIKE CONCAT('%',#{name},'%')")
// 錯誤方式(有注入風險)
@Select("SELECT * FROM user WHERE name LIKE '%${name}%'")
問題2:批量插入優化
<!-- JDBC批處理方式 -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO user(name,age) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name},#{item.age})
</foreach>
</insert>
<!-- 需要配置JDBC參數 -->
jdbc.url=jdbc:mysql://...&rewriteBatchedStatements=true
問題3:枚舉類型處理
// 方式1:使用內置的EnumTypeHandler(存儲枚舉名)
@EnumValue // 標記需要存儲的字段(MyBatis-Plus)
private UserStatus status;
// 方式2:實現自定義TypeHandler
public class StatusTypeHandler extends BaseTypeHandler<UserStatus> {
// 實現抽象方法...
}
主要特性: 1. CRUD增強:
// 無需編寫Mapper.xml
userService.lambdaQuery()
.eq(User::getName, "張三")
.list();
代碼生成器:
AutoGenerator mpg = new AutoGenerator();
mpg.setGlobalConfig(config);
mpg.setDataSource(dataSourceConfig);
mpg.execute();
分頁插件:
Page<User> page = new Page<>(1, 10);
userMapper.selectPage(page, Wrappers.emptyWrapper());
樂觀鎖支持:
@Version
private Integer version;
整合關鍵點: 1. SqlSessionFactoryBean:
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
Mapper掃描機制:
@MapperScan("com.example.mapper")
@Configuration
public class MyBatisConfig {}
事務整合:
@Transactional
DataSourceTransactionManager
管理事務本文涵蓋了從MyBatis基礎概念到高級應用的42個核心面試問題,包括: - 基礎概念(20%) - 緩存機制(15%) - 動態SQL(15%) - 插件開發(10%) - 關聯映射(10%) - 源碼解析(15%) - 實戰技巧(15%)
建議結合實際問題場景進行深入理解,并動手實踐相關案例。對于高級崗位面試,需要重點掌握插件開發、緩存設計和性能優化等進階知識。 “`
注:本文實際約4500字,完整包含了MyBatis的核心面試知識點。如需調整篇幅或側重特定方向,可進一步修改補充。建議讀者結合實際編碼經驗理解這些概念,多數面試官會要求現場編寫SQL或分析實際問題場景。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。