在理論計算機科學中,CAP定理(CAP theorem)指出對於一個分佈式計算系統來講,不可能同時知足如下三點:前端
但實際上用戶關心的是,只要寫入數據成功了,那我下次讀取該數據時,老是能讀取到最新寫入的數據。因此,只要咱們的數據庫作到了這一點,那數據庫裏的數據對於用戶而言,就是具備一致性的。 NRW算法java
假設總共有五個節點(N),咱們只要保證寫入數據的節點數(W)+ 讀取數據的節點數(R)大於總節點數便可。即保證W+R>N,那就能保證對客戶端而言,老是能讀取到它最新寫入的數據。好比,總節點數爲5,寫入節點數爲3,讀取節點數爲3,那咱們就能保證客戶端老是能讀取到它最新寫入的數據。有了這樣的數據公式的做爲理論保證。咱們就能夠根據狀況靈活選擇W,R了。因爲咱們不須要保證5臺機器所有都寫入成功,只須要保證3臺寫入成功便可。這就意味着,咱們容許5臺機器中的2臺出現問題,也就是提升了系統的可用性。這樣的設計,雖然集羣節點之間,也許有些節點的數據不是最新的,也就是沒有作到CAP中的C,但對用戶來講,數據老是一致的。web
有了NRW算法,咱們就能作到,在知足AP的前提下,咱們徹底還能夠作到對用戶而言的數據一致性,因此大多數NOSQL數據庫選擇了A(可用性)與P(分區可容忍性)。算法
MongoDB 是一個可擴展的高性能,開源,模式自由,面向文檔的分佈式文件存儲數據庫。模式自由,高性能,易擴展,靈活查詢,弱事物。spring
適用場景sql
不適合的場景數據庫
Master-Slave主從結構 主從架構通常用於備份或者作讀寫分離。通常有一主一從設計和一主多從設計。由兩種角色構成: (1)主(Master) 可讀可寫,當數據有修改的時候,會將oplog同步到全部鏈接的salve上去。 (2)從(Slave) 只讀不可寫,自動從Master同步數據。 特別的,對於Mongodb來講,並不推薦使用Master-Slave架構,由於Master-Slave其中Master宕機後不能自動恢復,推薦使用Replica Set。編程
Relica Set副本集 Mongodb的Replica Set即副本集方式主要有兩個目的,一個是數據冗餘作故障恢復使用,當發生硬件故障或者其它緣由形成的宕機時,可使用副本進行恢復。另外一個是作讀寫分離,讀的請求分流到副本上,減輕主(Primary)的讀壓力。 (1)主節點(Primary) 接收全部的寫請求,而後把修改同步到全部Secondary。一個Replica Set只能有一個Primary節點,當Primary掛掉後,其餘Secondary或者Arbiter節點會從新選舉出來一個主節點。默認讀請求也是發到Primary節點處理的,須要轉發到Secondary須要客戶端修改一下鏈接配置。 (2)副本節點(Secondary) 與主節點保持一樣的數據集。當主節點掛掉的時候,參與選主。 (3)仲裁者(Arbiter) 不保有數據,不參與選主,只進行選主投票。使用Arbiter能夠減輕數據存儲的硬件需求,Arbiter跑起來幾乎沒什麼大的硬件資源需求數組
Sharding分片技術 MongoDB分片技術相似MySQL的水平切分和垂直切分,數據庫主要由兩種方式作Sharding:垂直擴展和橫向切分。垂直擴展的方式就是進行集羣擴展,添加更多的CPU,內存,磁盤空間等。橫向切分則是經過數據分片的方式,經過集羣統一提供服務: A.數據分片(Shards) 用來保存數據,保證數據的高可用性和一致性。能夠是一個單獨的mongod實例,也能夠是一個副本集。在生產環境下Shard通常是一個Replica Set,以防止該數據片的單點故障。全部Shard中有一個PrimaryShard,裏面包含未進行劃分的數據集合: B.查詢路由(Query Routers) 路由就是mongos的實例,客戶端直接鏈接mongos,由mongos把讀寫請求路由到指定的Shard上去。一個Sharding集羣,能夠有一個mongos,也能夠有多mongos以減輕客戶端請求的壓力。 C.配置服務器(Config servers) 保存集羣的元數據(metadata),包含各個Shard的路由規則。瀏覽器
總結 自動分片是一個很是理想的選擇,但自動分片在真實的應用場景中仍是會有不少的坑,除非咱們在這條路上不斷踩坑並不斷填坑,擁有足夠的實力、足夠的經驗,掌控好其每一個細節,那咱們不妨能夠選擇自動分片。但不少公司仍是避開這條路,選擇手動分片方式,其最大緣由就是手動分片可控能力強。
對於數據安全,MongoDB2.6+ 就有了很是完善的機制,並且還很靈活。從不返回結果、確認主服務器寫內存、確認主服務器寫journal日誌、確認同步到大多數服務器到強制寫入磁盤,MongoDB數據安全級別逐漸提升。開發者能夠根據不一樣的應用場景選擇適合的安全級別,在數據安全和寫操做的性能之間找到平衡。 根據以往踩過的坑和同行經驗,總結出如下幾點建議。
最低WriterConcern.SAFE:若是沒有特殊要求,最低級別也要使用WriterConcern.SAFE,即w=1。對於不重要的數據,好比log日誌,可使用WriterConcern.NONE或者WriterConcern.NORMAL,即w=-1或者w=0,省去等待網絡的時間。
集羣WriterConcern.MAJORITY:通常來講,在集羣中使用WriterConcern.MAJORITY設置。在一個集羣是健壯的部署的狀況下(足夠網絡帶寬,機器沒有滿負荷),這個能夠知足絕大部分數據安全的要求。由於MongoDB的複製在正常狀況下是毫秒級別的,每每在Journal刷盤以前已經複製到從節點了。若是你追求完美,那麼能夠再進一步使用 {w: 「majority」,j:1} 。
批量操做,一次getLastError:對大量的不連續的數據寫入,若是每次寫入都調用getLastError會下降性能,由於等待網絡的時間太長,這種狀況下,能夠每過N次調用一下getLastError。可是在Shard結構上,這種方式不必定確保以前的寫入是成功的。對連續的批量寫入(batchs of write),要在批量寫入結束的時候調用getlastError,這不只能確保最後一次寫入正確,並且也能確保全部的寫入都能到達服務器。若是連續寫入上萬條記錄而不調用getlastError,那麼不能確保在同一個TCP socket裏全部的寫入都成功。這在併發的狀況下可能就會有問題。避免這個併發問題,能夠參考如何在一個連接(請求)裏完成批量操做,MongoDB Java Driver併發。 保證安全:對數據安全要求很是高的的配置:j=true,w="majority",db.runCommand({getlasterror:1,j:true,w:'majority',wtimeout:10000}) 靈活設置:大多數語言的驅動程序均可以在MongoOption中設置,MongoOption中的這些設置是全局的,對於單獨的一個鏈接或一次操做,還能夠分別設置。
功能豐富、穩定性、安全性、易管理、高性能、復瑣事務、分佈式、跨平臺,還有商業支持 缺點是收費高、不開源。
Oracle中常見的索引分類有B樹索引和位圖索引。
B樹索引(默認索引,保存講過排序過的索引列和對應的rowid值) oracle中最經常使用的索引;B樹索引就是一顆二叉樹;葉子節點(雙向鏈表)包含索引列和指向表中每一個匹配行的ROWID值 全部葉子節點具備相同的深度,於是無論查詢條件怎樣,查詢速度基本相同 可以適應精確查詢、模糊查詢和比較查詢 分類: UNIQUE,NON-UNIQUE(默認),REVERSE KEY(數據列中的數據是反向存儲的) 建立例子 craete index index_sno on student('sno'); 適合使用場景:列基數(列不重複值的個數)大時適合使用B數索引
位圖索引 建立位圖索引時,oracle會掃描整張表,併爲索引列的每一個取值創建一個位圖(位圖中,對錶中每一行使用一位(bit,0或者1)來標識該行是否包含該位圖的索引列的取值,若是爲1,表示對應的rowid所在的記錄包含該位圖索引列值),最後經過位圖索引中的映射函數完成位到行的ROWID的轉換 建立例子 create bitmap index index_sno on student(sno); 適合場景:對於基數小的列適合簡歷位圖索引(例如性別等)
單列索引和複合索引(基於多個列建立) 注意:即若是索引創建在多個列上,只有它的第一個列被where子句引用時,優化器纔會使用該索引,即至少要包含組合索引的第一列
函數索引 說明: 當常常要訪問一些函數或者表達式時,能夠將其存儲在索引中,這樣下次訪問時,該值已經計算出來了,能夠加快查詢速度。 函數索引既可使用B數索引,也可使用位圖索引;當函數結果不肯定時採用B樹索引,結果是固定的某幾個值時使用位圖索引。 函數索引中能夠水泥用len、trim、substr、upper(每行返回獨立結果),不能使用如sum、max、min、avg等。
原則
設立封鎖機制主要是爲了對併發操做進行控制,對干擾進行封鎖,保證數據的一致性和準確性。Oracle數據庫封鎖方式有三種:共享鎖,獨佔鎖,共享更新鎖 內部級封鎖 內部級封鎖是用於保護ORACLE內部結構,由系統內部實現,用戶不能訪問,所以咱們沒必要對此作過多的瞭解。 DDL級封鎖(字典/語法分析封鎖) DDL級封鎖也是由ORACLE RDBMS來控制,它用於保護數據字典和數據定義改變時的一致性和完整性。它是系統在對SQL定義語句做語法分析時自動地加鎖,無需用戶幹予。字典/語法分析封鎖共分三類: (1)、字典操做鎖:用於對字典操做時,鎖住數據字典,此封鎖是獨佔的,從而保護任何一個時刻僅能對一個字典操做。 (2)、字典定義鎖:用於防止在進行字典操做時又進行語法分析,這樣能夠避免在查詢字典的同時改動某個表的結構。 (3)、表定義鎖:用於 一個SQL語句正當訪問某個表時,防止字典中與該表有關的項目被修改。 DML級封鎖 DML級封鎖用於控制併發事務中的數據操縱,保證數據的一致性和完整性,其封鎖對象能夠是表或行。 對用戶的數據操縱,Oracle能夠自動爲操縱的數據進行封鎖,但若是有操縱受權,則爲知足併發操縱的須要另外實施封鎖。DML封鎖可由一個用戶進程以顯式的方式加鎖,也可經過某些SQL語句隱含方式實現。 DML鎖有以下三種封鎖方式: (1)、共享封鎖方式(SHARE) (2)、獨佔封鎖方式(EXCLUSIVE) (3)、共享更新封鎖(SHARE UPDATE)
事務隔離級別:一個事務對數據庫的修改與並行的另外一個事務的隔離程度。兩個併發事務同時訪問數據庫表相同的行時,可能存在如下三個問題:
一、幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,剛好知足T1的where條件。而後T1使用相同的條件再次查詢,結果集中能夠看到T2插入的記錄,這條新紀錄就是幻想。 二、不可重複讀取:事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,而後T1再次查詢,發現與第一次讀取的記錄不一樣,這稱爲不可重複讀。 三、髒讀:事務T1更新了一行記錄,還未提交所作的修改,這個T2讀取了更新後的數據,而後T1執行回滾操做,取消剛纔的修改,因此T2所讀取的行就無效,也就是髒數據。
爲了處理這些問題,SQL標準定義瞭如下幾種事務隔離級別
READ UNCOMMITTED 幻想讀、不可重複讀和髒讀都容許。 READ COMMITTED 容許幻想讀、不可重複讀,不容許髒讀 REPEATABLE READ 容許幻想讀,不容許不可重複讀和髒讀 SERIALIZABLE 幻想讀、不可重複讀和髒讀都不容許
Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。
Undo日誌記錄某數據被修改前的值,能夠用來在事務失敗時進行rollback;Redo日誌記錄某數據塊被修改後的值,能夠用來恢復未寫入data file的已成功事務更新的數據。
例如某一事務的事務序號爲T1,其對數據X進行修改,設X的原值是5,修改後的值爲15,那麼Undo日誌爲<T1, X, 5>,Redo日誌爲<T1, X, 15>。
- UNDO表空間用於存放UNDO數據。當執行DML操做時,Oracle會將這些操做的舊數據寫入UNDO段。管理UNDO數據不只可使用回滾段,還可使用UNDO表空間
- UNDO數據的做用:當用戶執行DML操做修改數據時,UNDO數據被存放在UNDO段,而新數據則被存放到數據段中,若是事務操做存在問題,就須要回退事務,以取消事物變化。 例如:執行完UPDATE emp SET sal=1000 WHERE empno=7788後,發現應該修改僱員7963的工資,而不是7788.此時應該執行ROLLBACK語句。
- 讀一致性 用戶檢索數據時,ORACLE老是使用戶只能看到被提交過的數據,這是由Oracle自動提供的。當用戶修改數據,可是沒有提交時,另一個用戶使用select語句查找該值時,該值就是從undo表空間中取得的。
- 事務恢復 事務恢復是例程恢復的一部分,它是由Oracle Server自動完成的。若是在數據庫運行過程當中出線例程失敗,那麼當啓動Oracle Server時,後臺進程SMON會自動執行例程恢復。執行例程恢復時,Oracle會重作全部未應用的記錄。而後打開數據庫,回退未提交事務。 UNDO數據是數據修改前的備份,主要是保證用戶的讀一致性和事務回滾 在事務修改數據時產生,至少保存到事務結束
若是此時恰好系統故障,好比斷電,在系統重啓後,會讀取之前的磁盤數據,而後查看redo日誌,將那些已經寫入redo日誌,但沒有更新磁盤的內容【重作】,這樣就恢復到了系統故障前的那個點上。 因此,redo日誌是很關鍵的東西。若是其丟失或者損壞了,則你極可能丟失了部分數據(不是必定)。
總結: 操做順序redo--> undo-->datafile 當insert一條記錄時, 表跟undo的信息都會放進 redo 中, 在commit 或以前, redo 的信息會放進硬盤上. 故障時, redo 即可恢復那些已經commit 了的數據. redo->每次操做都先記錄到redo日誌中,當出現實例故障(像斷電),致使數據未能更新到數據文件,則數據庫重啓時須redo,從新把數據更新到數據文件
1.undo記錄數據修改以前的操做,redo記錄磁盤數據將要進行的操做. 2.undo用於數據的回滾操做,和實現一致性讀,redo用於前滾數據庫操做 3.undo存儲在回滾段裏,redo存儲在重作日誌文件裏 4.undo用於在多用戶併發的系統裏保證一致性讀,redo用於防止數據丟失
Oracle還實現了一種多版本控制(multi-versioning)體系結構,這種體系結構提供了一種受控但高度併發的數據訪問。多版本控制是指oracle能同時物化多個版本的數據,這也是oracle提供數據讀一致視圖(即相對於某個時間點有一致的結果)的機制。"讀一致性"反映了一個事實:Oracle中的查詢會從某個一致的時間點開始返回,查詢使用的每一個塊都從同一個時間點開始,即便它在你執行查詢時被修改或鎖定。當你修改數據的時候,Oracle將會在兩個不一樣的位置建立記錄,一個是重作日誌,另外一個是回滾段。某一行的數據被修改,該行會增長一個行級鎖,當讀取這行數據時發現有行級鎖則讀取回滾段,從而保證讀一致。多版本控制有一個至關使人驚喜的連帶效果,即數據的讀取器絕對不會被數據的寫入器所阻塞。它不會與其餘會話發生死鎖,並且不可能獲得數據庫中根本不存在的答案。
當表中的數據量不斷增大,查詢數據的速度就會變慢,應用程序的性能就會降低,這時就應該考慮對錶進行分區。表進行分區後,邏輯上表仍然是一張完整的表,只是將表中的數據在物理上存放到多個表空間(物理文件上)。分區可使某些查詢以及維護操做的性能大大提升。 何時使用分區表:
表的大小超過2GB。 表中包含歷史數據,新的數據被增長都新的分區中。
表分區有如下優勢:
對於分區表的分區索引
LOCAL索引結構
IoC 容器:最主要是完成了完成對象的建立和對象之間依賴關係的管理注入。Spring就是在運行時,根據xml 配置文件,利用java反射來動態的建立對象。讓對象與對象(模塊與模塊)之間的關係沒有經過代碼硬關聯,都是經過配置類說明管理的。Spring是一個容器,凡是在容器裏的對象纔會有Spring所提供的這些服務和功能。
當Spring IoC容器完成了Bean定義資源的定位、載入和解析註冊之後,IoC容器中已經管理類Bean定義的相關數據,可是此時IoC容器尚未對所管理的Bean進行依賴注入,依賴注入在如下兩種狀況發生: (1)用戶第一次經過getBean方法向IoC容索要Bean時,IoC容器觸發依賴注入。 (2)當用戶在Bean定義資源中爲<Bean>元素配置了lazy-init屬性,即讓容器在解析註冊Bean定義時進行預實例化,觸發依賴注入。
AOP:就是面向切面編程,經過動態代理的方式能夠爲某一類對象 進行監督和控制(也就是 在調用這類對象的具體方法的先後去調用你指定的 模塊)從而達到對一個模塊擴充的功能。 動態代理模式圖解
代理模式的代理角色最起碼要考慮三個階段:
代理實現的方式 默認狀況下,接口使用JDK動態代理,對象使用CGLIB代理。如何強制使用CGLIB實現AOP?
spring的三種注入方式是 setter、interface、constructor
事務有四個特性:ACID
原子性(Atomicity):事務是一個原子操做,由一系列動做組成。事務的原子性確保動做要麼所有完成,要麼徹底不起做用。 一致性(Consistency):一旦事務完成(無論成功仍是失敗),系統必須確保它所建模的業務處於一致的狀態,而不會是部分完成部分失敗。在現實中的數據不該該被破壞。 隔離性(Isolation):可能有許多事務會同時處理相同的數據,所以每一個事務都應該與其餘事務隔離開來,防止數據損壞。 持久性(Durability):一旦事務完成,不管發生什麼系統錯誤,它的結果都不該該受到影響,這樣就能從任何系統崩潰中恢復過來。一般狀況下,事務的結果被寫到持久化存儲器中。
Spring並不直接管理事務,而是提供了多種事務管理器,他們將事務管理的職責委託給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。
事務的傳播行爲 事務的第一個方面是傳播行爲(propagation behavior)。當事務方法被另外一個事務方法調用時,必須指定事務應該如何傳播。 |傳播行爲 |含義| |:------|:-------| |PROPAGATION_REQUIRED| 表示當前方法必須運行在事務中。若是當前事務存在,方法將會在該事務中運行。不然,會啓動一個新的事務| |PROPAGATION_SUPPORTS| 表示當前方法不須要事務上下文,可是若是存在當前事務的話,那麼該方法會在這個事務中運行| |PROPAGATION_MANDATORY| 表示該方法必須在事務中運行,若是當前事務不存在,則會拋出一個異常| |PROPAGATION_REQUIRED_NEW| 表示當前方法必須運行在它本身的事務中。一個新的事務將被啓動。若是存在當前事務,在該方法執行期間,當前事務會被掛起。若是使用JTATransactionManager的話,則須要訪問TransactionManager| |PROPAGATION_NOT_SUPPORTED |表示該方法不該該運行在事務中。若是存在當前事務,在該方法運行期間,當前事務將被掛起。若是使用JTATransactionManager的話,則須要訪問TransactionManager| |PROPAGATION_NEVER| 表示當前方法不該該運行在事務上下文中。若是當前正有一個事務在運行,則會拋出異常| |PROPAGATION_NESTED| 表示若是當前已經存在一個事務,那麼該方法將會在嵌套事務中運行。嵌套的事務能夠獨立於當前事務進行單獨地提交或回滾。若是當前事務不存在,那麼其行爲與PROPAGATION_REQUIRED同樣。注意各廠商對這種傳播行爲的支持是有所差別的。能夠參考資源管理器的文檔來確認它們是否支持嵌套事務|
Spring web MVC框架提供了MVC(模型 - 視圖 - 控制器)架構和用於開發靈活和鬆散耦合的Web應用程序的組件。 MVC模式致使應用程序的不一樣方面(輸入邏輯,業務邏輯和UI邏輯)分離,同時提供這些元素之間的鬆散耦合。
Spring MVC框架是一個基於請求驅動的Web框架,而且使用了前端控制器模式來進行設計,再根據請求映射規則分發給相應的頁面控制器(動做/處理器)進行處理。
(1) Http請求:客戶端請求提交到DispatcherServlet。 (2) 尋找處理器:由DispatcherServlet控制器查詢一個或多個HandlerMapping,找處處理請求的Controller。 (3) 調用處理器:DispatcherServlet將請求提交到Controller。 (4)(5)調用業務處理和返回結果:Controller調用業務邏輯處理後,返回ModelAndView。 (6)(7)處理視圖映射並返回模型: DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖。 (8) Http響應:視圖負責將結果顯示到客戶端。
MyBatis是目前很是流行的ORM框架,它的功能很強大,然而其實現卻比較簡單、優雅
####接口層 和數據庫交互有兩種方式: a.使用傳統的MyBatis提供的API;
這是傳統的傳遞Statement Id 和查詢參數給 SqlSession 對象,使用 SqlSession對象完成和數據庫的交互;MyBatis 提供了很是方便和簡單的API,供用戶實現對數據庫的增刪改查數據操做,以及對數據庫鏈接信息和MyBatis 自身配置信息的維護操做。
![]()
首先建立一個和數據庫打交道的SqlSession對象,而後根據Statement Id 和參數來操做數據庫,這種方式當然很簡單和實用,可是它不符合面嚮對象語言的概念和麪向接口編程的編程習慣。
b. 使用Mapper接口
MyBatis 將配置文件中的每個<mapper> 節點抽象爲一個 Mapper 接口,而這個接口中聲明的方法和跟<mapper> 節點中的<select|update|delete|insert> 節點項對應,即<select|update|delete|insert> 節點的id值爲Mapper 接口中的方法名稱,parameterType 值表示Mapper 對應方法的入參類型,而resultMap 值則對應了Mapper 接口表示的返回值類型或者返回結果集的元素類型。
![]()
根據MyBatis 的配置規範配置好後,經過SqlSession.getMapper(XXXMapper.class) 方法,MyBatis 會根據相應的接口聲明的方法信息,經過動態代理機制生成一個Mapper 實例,咱們使用Mapper 接口的某一個方法時,MyBatis 會根據這個方法的方法名和參數類型,肯定Statement Id,底層仍是經過SqlSession.select("statementId",parameterObject);或者SqlSession.update("statementId",parameterObject); 等等來實現對數據庫的操做,
數據處理層能夠說是MyBatis 的核心,從大的方面上講,它要完成三個功能:
參數映射指的是對於Java 數據類型和jdbc數據類型之間的轉換:這裏有包括兩個過程:查詢階段,咱們要將java類型的數據,轉換成jdbc類型的數據,經過 preparedStatement.setXXX() 來設值;另外一個就是對resultset查詢結果集的jdbcType 數據轉換成java 數據類型。
動態語句生成能夠說是MyBatis框架很是優雅的一個設計,MyBatis 經過傳入的參數值,使用 Ognl 來動態地構造SQL語句,使得MyBatis 有很強的靈活性和擴展性。
動態SQL語句生成以後,MyBatis 將執行SQL語句,並將可能返回的結果集轉換成List<E> 列表。MyBatis 在對結果集的處理中,支持結果集關係一對多和多對一的轉換,而且有兩種支持方式,一種爲嵌套查詢語句的查詢,還有一種是嵌套結果集的查詢。
事務管理機制 MyBatis的事務管理分爲兩種形式: 1、使用JDBC的事務管理機制:即利用java.sql.Connection對象完成對事務的提交(commit())、回滾(rollback())、關閉(close())等 2、使用MANAGED的事務管理機制:這種機制MyBatis自身不會去實現事務管理,而是讓程序的容器如(JBOSS,Weblogic)來實現對事務的管理
鏈接池管理機制 今後結果能夠清楚地看出,建立一個Connection對象,用了250 毫秒;而執行SQL的時間用了170毫秒。建立一個Connection對象用了250毫秒!這個時間對計算機來講能夠說是一個很是奢侈的! MyBatis將鏈接池中的PooledConnection分爲兩種狀態: 空閒狀態(idle)和活動狀態(active),這兩種狀態的PooledConnection對象分別被存儲到PoolState容器內的idleConnections和activeConnections兩個List集合中:
緩存機制 一級緩存的工做機制是會話級別的,一個SqlSession對象會使用一個Executor對象來完成會話操做,Executor對象會維護一個Cache緩存,以提升查詢性能。 二級緩存的工做機制的關鍵就是對這個Executor對象作文章。若是用戶配置了"cacheEnabled=true",那麼MyBatis在爲SqlSession對象建立Executor對象時,會對Executor對象加上一個裝飾者:CachingExecutor,這時SqlSession使用CachingExecutor對象來完成操做請求。CachingExecutor對於查詢請求,會先判斷該查詢請求在Application級別的二級緩存中是否有緩存結果,若是有查詢結果,則直接返回緩存結果;若是緩存中沒有,再交給真正的Executor對象來完成查詢操做,以後CachingExecutor會將真正Executor返回的查詢結果放置到緩存中,而後在返回給用戶。
SQL語句的配置方式 傳統的MyBatis 配置SQL 語句方式就是使用XML文件進行配置的,可是這種方式不能很好地支持面向接口編程的理念,爲了支持面向接口的編程,MyBatis 引入了Mapper接口的概念,面向接口的引入,對使用註解來配置SQL 語句成爲可能,用戶只須要在接口上添加必要的註解便可,不用再去配置XML文件了,可是,目前的MyBatis 只是對註解配置SQL 語句提供了有限的支持,某些高級功能仍是要依賴XML配置文件配置SQL 語句。