程式設計補完計畫(一): mybatis
程式設計補完計畫(一): mybatis
因為一些原因我發現自己一直以來都只有在寫程式,沒有認真想過為甚麼要用這個 Lib 或框架。
因此想透過這個系列重新審視自己身邊常用的 Lib。
第一集我想要先聊 Mybatis,基本上所有跟 ORM 有關的開發我都會用 Mybatis 去處理,但沒有認真探討過為甚麼要用和甚麼時候用。
那就先開始吧。
簡介(來自 wiki)
MyBatis 不是物件與資料庫表關聯,而是將Java方法與SQL語句關聯。MyBatis允許使用者充分利用資料庫的各種功能,例如儲存程序、視圖、各種複雜的查詢以及某資料庫的專有特性。如果要對遺留資料庫、不規範的資料庫進行操作,或者要完全控制SQL的執行,MyBatis是一個不錯的選擇。
優點:
先將優點列出之後一項一項說明
- sql 與 Java 程式碼分離
- MyBatis支持許多高級映射和存儲過程,使得更複雜的數據庫操作更容易。
- MyBatis支持基於Spring、Guice等框架的注入,這意味著可以更輕鬆地集成到現有的應用程序中。
- 由於 Mybatis 需要直接寫 sql,因此可以做更細和更複雜的 sql 操作。
- 提供緩存機制,在搜尋資料時可以提高效率。
sql 與 Java 程式碼分離
MyBatis 可以將 sql 寫在另外的 xml 檔案中,也可以透過 annotation 寫 sql ,因此不會看到還先用 String 組成 sql 後執行的情況發生。
MyBatis支持許多高級映射和存儲過程,使得更複雜的數據庫操作更容易。
MyBatis 在 xml 中提供了,if, where 等語法,讓 sql 在組合時會更簡單,例如透過 <if>
判斷特定變數是否為 null
,如果是 null 就不要加入 set 裡面。
<where>
和 <if>
搭配的話就可以很簡單的組合出 where 條件,詳細的內容可以參考這個網站:
https://mybatis.org/mybatis-3/dynamic-sql.html
Mybatis 可以很好的跟 spring 整合
再重複說一次,Mybatis 可以很好的跟 spring 整合。
這一點很重要,這代表著服務初期可以透過 spring jpa 或其他 ORM 框架設計,當服務足夠大導致出現 DB 效能瓶頸的時候在改用 Mybatis。
提供緩存機制,在搜尋資料時可以提高效率。
MyBatis 提供了三種緩存機制,主要是為了讓重複的資料在搜尋時不需要再去 DB 搜尋,而是直接在緩存取得資料,從而降低 DB 的負擔。
但需要注意!對於經常更新的資料不適合使用緩存機制,因為這很有可能會導致緩存資料和 DB 實際資料不相同。
下面簡單說明三種緩存:
一級緩存(Local Cache)
這是默認會開啟的緩存機制,同一個 SqlSession 跑同一個 SQL 語句的時候就會直接從緩存取得,但一離開 SqlSession 就會被清空。
二級緩存(Global Cache)
剛剛一級緩存是綁 SqlSession 的,二級緩存是跨 SqlSession 的,二級緩存必須在映射文件(如: xml 檔)宣告才會啟用。
注意: 二級緩存不會知道 DB 的資料有更改,我們必須寫 code 或設定二級緩存的固定更新時間。
聯合緩存 (Combined Cache)
聯合緩存是同時使用一級緩存和二級緩存。當數據被寫入數據庫時,一級緩存和二級緩存都會被更新。當數據被讀取時,首先會從一級緩存中查找,如果沒有找到,才會從二級緩存中查找。如果在二級緩存中也沒有找到,才會向數據庫中查詢。在 MyBatis 中啟用聯合緩存需要同時在映射文件和全局配置文件中進行配置。
題外話
甚麼是不常更改的數據? 像是: 郵遞區號,商品分類。
甚麼是常更改的數據? 像是: 庫存更新。
如何清除二級緩存? 根據情況可以考慮開一個 API 專門用於清楚二級緩存,或像前面提到的設定二級緩存的更新週期。
缺點
- 需要會 sql,提高學習曲線
- 需要設定映射配置
- 可能出現重複的程式碼
- 執行前可能不會發現 SQL 寫錯了
- MyBatis 的性能與 SQL 的質量、緩存配置有問題的話會發生性能問題
需要會 sql,提高學習曲線
這有點像雙面刃,會寫 sql 的人可以透過檢查 table 的 index 寫出高效率的 sql 語句,但就是需要花時間去了解。
需要設定映射配置
常見的 mybatis 寫法會在 Java 寫一個 index 之後再寫一個 xml 去搭配,因此我們需要跟 spring 或其他框架說 xml 放在哪裡,但如果以 spring boot 來說的話配置通常不會太複雜。
可能出現重複的程式碼
因為會需要依照不同情境寫不同 SQL 的 where 條件,但這部分可以參考剛剛前面提到的 <if>
<where>
tag 生成動態 sql 就可以解決了。
執行前可能不會發現 SQL 寫錯了
由於 SQL 都是寫在 xml 裡面,在編譯 Java 時 mybatis 並不會檢查 SQL 語法,因此有可能會在執行到該 SQL 時才發生錯誤。
MyBatis 的性能與 SQL 的質量、緩存配置有問題的話會發生性能問題
如果寫 SQL 的經驗不多可能會導致 DB 搜尋時間很久(如 join 大量的 table 等),錯誤的決定緩存策略可能會導致緩存取得的資料與 DB 不符從而影響後續的邏輯判斷。
總結
統整起來看的話如果沒有複雜sql需求的話會有其他更好的選擇,比如spring jpa等,但如果今天sql是需要使用特定index或需要靈活組合 sql 的話 mybatis 會是不錯的選擇。
留言
張貼留言