Mybatis源码:Executor 模板模式
by yan 20220301
模板模式
在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬于行為型模式。
意圖:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
主要解決:一些方法通用,卻在每一個子類都重新寫了這一方法。
何時使用:有一些通用的方法。
如何解決:將這些通用算法抽象出來。
關鍵代碼:在抽象類實現,其他步驟在子類實現。
應用實例: 1、在造房子的時候,地基、走線、水管都一樣,只有在建筑的后期才有加壁櫥加柵欄等差異。 2、西游記里面菩薩定好的 81 難,這就是一個頂層的邏輯骨架。 3、spring 中對 Hibernate 的支持,將一些已經定好的方法封裝起來,比如開啟事務、獲取 Session、關閉 Session 等,程序員不重復寫那些已經規范好的代碼,直接丟一個實體就可以保存。
優點: 1、封裝不變部分,擴展可變部分。 2、提取公共代碼,便于維護。 3、行為由父類控制,子類實現。
缺點:每一個不同的實現都需要一個子類來實現,導致類的個數增加,使得系統更加龐大。
使用場景: 1、有多個子類共有的方法,且邏輯相同。 2、重要的、復雜的方法,可以考慮作為模板方法。
注意事項:為防止惡意操作,一般模板方法都加上 final 關鍵詞。
創建Executor
在openSqlSession中創建Executor
Mybatis insert
時序圖: insert 過程
Mybatis Executor 相關類圖
BaseExecutor :實現了Executor的全部方法,包括對緩存,事務,連接提供了一系列的模板方法, 這些模板方法中留出來了四個抽象的方法等待子類去實現如下
protected abstract int doUpdate(MappedStatement ms, Object parameter)throws SQLException;protected abstract List<BatchResult> doFlushStatements(boolean isRollback)throws SQLException;protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)throws SQLException;protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)throws SQLException; //模板方法@Overridepublic 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);}@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {BoundSql boundSql = ms.getBoundSql(parameter);CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}@SuppressWarnings("unchecked")@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack == 0) {for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load();}// issue #601deferredLoads.clear();if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}@Overridepublic <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {BoundSql boundSql = ms.getBoundSql(parameter);return doQueryCursor(ms, parameter, rowBounds, boundSql);}SimpleExecutor: 特點是每次執行完畢后都會將創建出來的statement關閉掉,他也是默認的執行器類型
ReuseExecutor: 在它在本地維護了一個容器,用來存放針對每條sql創建出來的statement,下次執行相同的sql時,會先檢查容器中是否存在相同的sql,如果存在就使用現成的,不再重復獲取
BatchExecutor: 特點是進行批量修改,她會將修改操作記錄在本地,等待程序觸發提交事務,或者是觸發下一次查詢時,批量執行修改
BaseExecutor與一級緩存
BaseExecutor維護的一級緩存。
一級緩存是sqlsession級的:
sqlsession->excutor->localcache
什么是這個一級緩存呢? **一級緩存就是上面代碼中的localCache。
一級緩存叫localCache,它的封裝類叫PerpetualCache。
perpetual意味永不間斷,一級緩存默認存在,也關不了。
但是在與Spring整合時,Spring把這個緩存給關了,這并不奇怪,因為spring 直接干掉了這個sqlSession。
一級緩存什么時候被填充的值呢?填充值的操作在一個叫做queryFromDataBase()的方法里面。
清空一級緩存的方法就是BaseExecutor的update()模板方法里。
CachingExecutor與二級緩存
二級緩存是共享級,在configuration里的。在mapper builder 加載配置 build時創建的。
//Configuration.javaprotected final Map<String, Cache> caches = new StrictMap<>("Caches collection");CachingExecutor通過TransactionalCacheManager可能獲取二級緩存里的數據。
二級緩存中存放的不是對象,而是被序列化后存儲的數據,需要反序列化出來。
參考
:
https://
www.runoob.com/design-pattern/template-pattern.html
https://www.cnblogs.com/ZhuChangwu/p/11745562.html
總結
以上是生活随笔為你收集整理的Mybatis源码:Executor 模板模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一起学微软Power BI系列-使用技巧
- 下一篇: Mybatis源码: Builder M