首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 學習總結:最佳實踐與優化建議指南

     編輯:Java 相關知識

MyBatis 學習總結:核心優化建議與最佳實踐

MyBatis (前身 iBatis) 是優秀的持久層框架,支援自定義 SQL、存儲過程與高級映射。本文總結實戰中積累的核心優化建議,助你避開常見坑點,編寫高效可維護的資料存取層。

核心優化原則

1. Mapper 參數使用 Map,由 Service 層負責重載

問題:Mapper 介面不支援方法重載,若直接使用多參數會導致參數含義模糊。

建議:Mapper 參數統一使用 Map,在 Service 層提供重載方法,對外暴露清晰的方法簽名。

// Mapper 介面
User selectByParams(Map<String, Object> params);

// Service 層重載
public User getById(Long id) { return mapper.selectByParams(Map.of("id", id)); }
public User getByName(String name) { return mapper.selectByParams(Map.of("name", name)); }
public User getByIdAndName(Long id, String name) { 
    return mapper.selectByParams(Map.of("id", id, "name", name)); 
}

優勢:方法簽名自文檔化,參數類型/個數/含義一目瞭然,重構時編譯器可檢查,避免 Map 鍵名拼寫錯誤。

2. 極少使用 <if> <choose> 動態 SQL,下降維護難度

問題:大量動態標籤導致 SQL 複雜難讀、調試困難、產生大量空白字元、引發 Oracle 硬解析。

建議:優先使用 SQL 原生函數處理條件邏輯。

反例:大量 if/choose
<select id="selectNews" resultType="News">
  SELECT * FROM T_NEWS_TEXT WHERE 1=1
  <choose>
    <if test="startdate != null and enddate != null">
      AND PUBLISHTIME >= #{startdate} AND PUBLISHTIME <= #{enddate}
    </if>
    <otherwise>
      AND PUBLISHTIME >= SYSDATE - 7 AND PUBLISHTIME <= SYSDATE
    </otherwise>
  </choose>
</select>
優化:使用 DECODE/CASE WHEN
<select id="selectNews" resultType="News">
  SELECT * FROM T_NEWS_TEXT 
  WHERE PUBLISHTIME >= DECODE(#{startdate}, NULL, SYSDATE-7, #{startdate})
  AND PUBLISHTIME <= DECODE(#{enddate}, NULL, SYSDATE, #{enddate})
</select>

補充:預設值處理應前移至 Service/Controller 層,便於快取鍵值確定。

3. 使用 XML 註釋替代 SQL 註釋

問題:SQL 單行註釋 (--) 在分頁插件包裝 SQL 時會導致後續條件被註釋掉,極難排查。

建議:統一使用 XML 註釋 <!-- -->,不會出現在生成的 SQL 中。

<!-- 正確:XML 註釋 -->
<select id="query">
  SELECT * FROM TEST WHERE COL1 > 1
  <if test="a != null">AND COL2 = #{a}</if>
</select>

-- 錯誤:SQL 註釋會吞噬後續動態標籤
SELECT * FROM TEST WHERE COL1 > 1 -- 這是註釋
<if test="a != null">AND COL2 = #{a}</if>

4. 盡量使用 #{} 而非 ${}

問題:${} 為字串直接替換,導致 SQL 注入風險、Oracle 硬解析、效能下降。

建議:

  • 參數綁定一律使用 #{} (PreparedStatement)
  • IN 查詢:使用 <foreach> 或自定義 TypeHandler
  • LIKE 查詢:title LIKE CONCAT('%', #{keyword}, '%') 或 title LIKE #{keyword} || '%'
  • 動態表名/欄位名:考慮存儲過程或嚴格白名單驗證

5. 簡單使用 MyBatis,不做複雜邏輯

MyBatis 定位為 SQL 映射與簡單 ORM,避免在映射文件中實現複雜業務邏輯、字串處理、流程控制。複雜邏輯應在 Service 層用 Java 完成。

進階建議

  • ResultMap 顯式映射:避免 resultType 隱式映射導致欄位名變更時運行時報錯
  • 分頁插件:使用 PageHelper 等成熟插件,勿自行拼接 LIMIT/OFFSET
  • 批次操作:大量寫入使用 ExecutorType.BATCH 或 <foreach> 批次 INSERT
  • 二級快取:謹慎開啟,適合讀多寫少、容許髒讀的參考資料
  • SQL 審計:開啟 logImpl=STDOUT_LOGGING 監控執行 SQL 與參數

總結

MyBatis 核心優勢在於 SQL 完全可控,但也要求開發者具備良好的 SQL 功力與資料庫知識。遵循「Service 層重載、SQL 原生邏輯、XML 註釋、#{} 參數化、職責單一」五大原則,能顯著提升代碼可維護性與系統效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved