程式設計補完計畫(一): 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 會是不錯的選擇。

留言

這個網誌中的熱門文章

基本 Spring security 快速入門

記帳專案說明

JMSTemplate 的教學