1、mybatis源碼分析面試
1.mybatis功能架構sql
2. SQL調用過程(mybatis工做原理)數據庫
mybatis經過配置文件建立sqlsessionFactory,sqlsessionFactory根據配置文件,配置文件來源於兩個方面:一個是xml,一個是Java中的註解,獲取sqlSession。SQLSession包含了執行sql語句的全部方法,能夠經過SQLSession直接運行映射的sql語句,完成對數據的增刪改查和事物的提交工做,用完以後關閉SQLSession。 緩存
3. mybatis的SqlSessionFactory 與 SqlSession.安全
(1)首先,SqlSessionFactoryBuilder去讀取mybatis的配置文件,而後build一個DefaultSqlSessionFactory。session
(2)當咱們獲取到SqlSessionFactory以後,就能夠經過SqlSessionFactory去獲取SqlSession對象。mybatis
4. 利器之MapperProxy:架構
在mybatis中,經過MapperProxy動態代理我們的dao(mapper), 也就是說, 當我們執行本身寫的dao裏面的方法的時候,實際上是對應的mapperProxy在代理。app
(1)經過SqlSession從Configuration中獲取。框架
(2)SqlSession把包袱甩給了Configuration, 接下來就看看Configuration。
(3)Configuration不要這燙手的山芋,接着甩給了MapperRegistry, 那咱看看MapperRegistry。
(4)MapperRegistry經過調用newInstance動態代理咱們寫的dao接口。
5.Excutor
6.mybatis的緩存
6.1 一級緩存的做用域是SqlSession
Executor接口的實現類是由Configuration構造的:
public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor, autoCommit);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
最後咱們發現若是cacheEnabled這個屬性爲true的話,那麼executor會被包一層裝飾器,這個裝飾器是CachingExecutor。其中cacheEnabled這個屬性是mybatis總配置文件中settings節點中cacheEnabled子節點的值,默認就是true,也就是說咱們在mybatis總配置文件中不配cacheEnabled的話,它也是默認爲打開的。
CachingExecutor執行sql的時候到底作了什麼?
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();//這兒執行的是二級緩存
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
if (!dirty) {
cache.getReadWriteLock().readLock().lock();
try {
@SuppressWarnings("unchecked")
List<E> cachedList = (List<E>) cache.getObject(key);
if (cachedList != null) return cachedList;
} finally {
cache.getReadWriteLock().readLock().unlock();
}
}
List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
return list;
}
}
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
因爲咱們沒有開啓二級緩存(二級緩存的內容下面會分析),所以這裏執行了最後一句話。因此一級緩存最重要的代碼就是BaseExecutor的query方法! 這個localCache就是一級緩存!
接下來咱們看下爲什麼執行新增或更新或刪除操做,一級緩存就會被清除這個問題。
CachingExecutor的update方法
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);//這清除的是二級緩存
return delegate.update(ms, parameterObject);
}
BaseExecutor的update方法:
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
clearLocalCache();
return doUpdate(ms, parameter);
}
6.2 二級緩存
二級緩存的做用域是全局,換句話說,二級緩存已經脫離SqlSession的控制了。二級緩存的做用域是全局的,二級緩存在SqlSession關閉或提交以後纔會生效。
本文就說下最簡單的配置,在mapper文件上加上這句配置便可:<
cache
/>
2、面試相關
1.mybatis是什麼?
mybatis是一個優秀的持久層框架,他對jdbc操做數據庫的過程進行了封裝,使開發着只用關注sql自己,不用去關注例如註冊驅動,加載連接,獲得statement,處理結果集等複雜的過程。
mybatis經過xml或者註解的方式,將要執行的各類sql語句配置起來,並經過Java對象和statement中的sql語句映射生成最終的sql語句,最後由mybatis框架執行sql語句,並將結果映射成Java對象返回。
2.mybatis解決的問題
3. #{}和${}的區別是什麼?
#{}是預編譯處理,${}是字符串替換。 Mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值; Mybatis在處理${}時,就是把${}替換成變量的值。 使用#{}能夠有效的防止SQL注入,提升系統安全性。
4.Mybatis是如何進行分頁的?分頁插件的原理是什麼?
Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁,能夠在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可使用分頁插件來完成物理分頁。 分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,而後重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
5.什麼是延遲加載
延遲加載的實例:
若是查詢訂單而且關聯查詢用戶信息。若是先查詢訂單信息便可知足要求,當咱們須要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
二者相同點
Hibernate與 MyBatis均可以是經過SessionFactoryBuider由XML配置文件生成SessionFactory,而後由 SessionFactory 生成Session,最後由Session來開啓執行事務和SQL語句。其中 SessionFactoryBuider,SessionFactory,Session的生命週期都是差很少的。
Hibernate和MyBatis都支持JDBC和JTA事務處理。
Mybatis優點
MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。
MyBatis容易掌握,而Hibernate門檻較高。
Hibernate優點
Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射。
Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。
Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。
Hibernate有更好的二級緩存機制。Hibernate緩存分爲:
一級緩存:session共享(save、update、saveOrupdate、load、get、list) 用於處理當前的單元操做.
二級緩存:sessionFactory共享.(常常讀不多被修改,若是使用二級緩存能夠提升性能.)
MyBatis自己提供的緩存機制不佳。MyBatis 包含一個很是強大的查詢緩存特性,它能夠很是方便地配置和定製。默認狀況下是沒有開啓緩存的,除了局部 的 session 緩存,能夠加強變現並且處理循環依賴也是必須的。要開啓二級緩存,你須要在你的 SQL 映射文件中添加一行: <cache/>
hibernate中session打開和關閉由sessionFactory的getSession()來管理session的打開和關閉。
第三方緩存實現:cache、Map等;