mybatis面試常見問題
MyBatis
FAQ
- MyBatis 基礎 1-1
1.1. MyBatis 是什麼? 1-1
1.2. MyBatis 應用場景? 1-1
1.3. MyBatis 核心物件有哪些? 1-1
1.4. MyBatis程式設計步驟是什麼樣的? 1-2
1.5. MyBatis 對映檔案元素解析時對應哪些物件? 1-2 - MyBatis 進階 2-2
2.1. #{}和${}的區別是什麼? 2-2
2.2. MyBatis 中TypeHandler有什麼作用以及應用場景? 2-2
2.3. MyBatis 中TypeHandler如何編寫以及配置? 2-3
2.4. MyBatis 動態SQL如何理解及常用元素? 2-4
2.5. 簡述Mybatis的外掛執行原理,以及如何編寫一個外掛? 2-4
2.6. Mybatis是否支援延遲載入?如果支援,它的實現原理是什麼? 2-4
2.7. Mybatis都有哪些Executor執行器?它們之間的區別是什麼? 2-5
2.8. MyBatis 日誌處理應如何配置? 2-5
2.9. MyBatis 快取設計及配置? 2-5
1.MyBatis 基礎
1.1.MyBatis 是什麼?
是一個優秀的資料持久層框架,主要負責資料的持久化以及對映操作。
1.2.MyBatis 應用場景?
MyBatis底層封裝了JDBC中的一些通用性操作,主要用於在JAVA的生態系統中簡化JDBC的資料持久化以及ORM操作。
1.3.MyBatis 核心物件及元件有哪些?
API:
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
Xml
1)配置
2)對映檔案
1.4.MyBatis程式設計步驟是什麼樣的?
① 建立SqlSessionFactory
② 通過SqlSessionFactory建立SqlSession
③ 通過sqlsession執行資料庫操作
④ 呼叫session.commit()提交事務
⑤ 呼叫session.close()關閉會話
1.5.MyBatis 對映檔案元素解析時對應哪些物件?
1)每一個、、、標籤均會被解析為MappedStatement物件,標籤內的sql會被解析為BoundSql物件。
2)標籤會被解析為ResultMap物件,其每個子元素會被解析為ResultMapping物件
2.MyBatis 進階
2.1.#{}和${}的區別是什麼?
#{}是預編譯處理,KaTeX parse error: Expected 'EOF', got '#' at position 21: …串替換。 Mybatis在處理#̲{}時,會將sql中的#{}替…{}時,就是把${}替換成變數的值。
使用#{}可以有效的防止SQL注入,提高系統安全性。
2.2.MyBatis 中TypeHandler有什麼作用以及應用場景?
TypeHandler主要有兩個作用,一是完成從javaType至jdbcType的轉換,二是完成jdbcType至javaType的轉換,具體體現為setParameter()和getResult()兩個方法,分別代表設定sql問號佔位符引數和獲取列查詢結果。
typeHandler專門用來解決資料庫中的資料型別和Java中的資料型別之間的轉化問題, 事實上,mybatis本身已經為我們提供了許多typeHandler了,系統提供的typeHandler能夠滿足我們日常開發中的大部分需求,但是現在要將list集合中的的資料以指定格式寫入到資料庫(例如{xxx,xxx,xxx}),或從資料庫讀取的這樣的資料到list集合。
2.3.MyBatis 中TypeHandler如何編寫以及配置?
自定義typeHandler我們有兩種方式,一種是實現TypeHandler介面,還有一種簡化的寫法就是繼承自BaseTypeHandler類,瞭解如下類基本配置
@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({Date.class})
class MyDateTypeHandler extends BaseTypeHandler {
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, String.valueOf(date.getTime()));
}
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
return new Date(resultSet.getLong(s));
}
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
return new Date(resultSet.getLong(i));
}
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return callableStatement.getDate(i);
}
}
在Mapper中進行配置
INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR,typeHandler=org.sang.db.MyDateTypeHandler})2.4.MyBatis 動態SQL如何理解及常用元素?
Mybatis動態sql可以讓我們在Xml對映檔案內,以標籤的形式編寫動態sql,完成邏輯判斷和動態拼接sql的功能,Mybatis提供了9種動態sql標籤
trim|where|set|foreach|if|choose|when|otherwise|bind。
2.5.簡述Mybatis的外掛執行原理,以及如何編寫一個外掛?
Mybatis僅可以編寫針對ParameterHandler、ResultSetHandler、StatementHandler、Executor這4種介面的外掛,Mybatis使用JDK的動態代理,為需要攔截的介面生成代理物件以實現介面方法攔截功能,每當執行這4種介面物件的方法時,就會進入攔截方法,具體就是InvocationHandler的invoke()方法,當然,只會攔截那些你指定需要攔截的方法。
實現Mybatis的Interceptor介面並複寫intercept()方法,然後在給外掛編寫註解,指定要攔截哪一個介面的哪些方法即可,記住,別忘了在配置檔案中配置你編寫的外掛。
2.6.Mybatis是否支援延遲載入?如果支援,它的實現原理是什麼?
Mybatis僅支援association關聯物件和collection關聯集合物件的延遲載入,association指的就是一對一,collection指的就是一對多查詢。在Mybatis配置檔案中,可以配置是否啟用延遲載入lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB建立目標物件的代理物件,當呼叫目標方法時,延遲載入關聯物件。
2.7.Mybatis都有哪些Executor執行器?它們之間的區別是什麼?
Mybatis有三種基本的Executor執行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每執行一次update或select,就開啟一個Statement物件,用完立刻關閉Statement物件。
ReuseExecutor:執行update或select,以sql作為key查詢Statement物件,存在就使用,不存在就建立,用完後,不關閉Statement物件,而是放置於Map<String, Statement>內,供下一次使用。簡言之,就是重複使用Statement物件。
BatchExecutor:執行update(沒有select,JDBC批處理不支援select),將所有sql都新增到批處理中(addBatch()),等待統一執行(executeBatch()),它快取了多個Statement物件,每個Statement物件都是addBatch()完畢後,等待逐一執行executeBatch()批處理。與JDBC批處理相同。
作用範圍:Executor的這些特點,都嚴格限制在SqlSession生命週期範圍內。
2.8.MyBatis 日誌處理應如何配置?
???????
Log4j.propertes
Log4j2.xml
2.9.MyBatis 快取設計及配置?
MyBatis 一級快取概述及總結:
MyBatis一級快取的生命週期和SqlSession一致。
MyBatis一級快取內部設計簡單,只是一個沒有容量限定的HashMap,在快取的功能性上有所欠缺。
MyBatis的一級快取最大範圍是SqlSession內部,有多個SqlSession或者分散式的環境下,資料庫寫操作會引起髒資料,建議設定快取級別為Statement。
MyBatis 二級快取及概述?
如果多個SqlSession之間需要共享快取,則需要使用到二級快取。開啟二級快取後,會使用CachingExecutor裝飾Executor,進入一級快取的查詢流程前,先在CachingExecutor進行二級快取的查詢。二級快取開啟後,同一個namespace下的所有操作語句,都影響著同一個Cache,即二級快取被多個SqlSession共享,是一個全域性的變數。
當開啟快取後,資料的查詢執行的流程就是 二級快取 -> 一級快取 -> 資料庫。
MyBatis的二級快取相對於一級快取來說,實現了SqlSession之間快取資料的共享,同時粒度更加的細,能夠到namespace級別,通過Cache介面實現類不同的組合,對Cache的可控性也更強。
MyBatis在多表查詢時,極大可能會出現髒資料,有設計上的缺陷,安全使用二級快取的條件比較苛刻。
在分散式環境下,由於預設的MyBatis Cache實現都是基於本地的,分散式環境下必然會出現讀取到髒資料,需要使用集中式快取將MyBatis的Cache介面實現,有一定的開發成本,直接使用Redis,Memcached等分散式快取可能成本更低,安全性也更高。