Java + Spring Boot + MyBatis 枚舉變量傳遞給XML映射文件做判斷

枚舉定義?ReagentStatus.java

package com.weiyu.utils.enums;import lombok.Getter;/*** 試劑狀態枚舉*/
@Getter
public enum ReagentStatus {// 常規REGULAR,// 少庫存LESS_INVENTORY,// 零庫存ZERO_INVENTORY,// 將過期WILL_EXPIRE,// 已過期EXPIRED,// 已注銷LOGGED,// 全部ALL
}

查詢對象 DTO?ReagentQueryDTO.java

package com.weiyu.pojo;import com.weiyu.utils.enums.ReagentStatus;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;/*** 試劑管理查詢 DTO*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReagentQueryDTO {// 分頁器private PageHelper pageHelper = new PageHelper(1, 20);// 試劑類型private String reagentCategory;// 試劑編號private String reagentNo;// 試劑名稱private String reagentName;// 試劑狀態private ReagentStatus status;// 當天零晨,用于過濾有效期private LocalDateTime currentStartOfDay;
}

ReagentMapper.java

    // 通過狀態,查詢試劑列表List<Reagent> selectByStatus(ReagentQueryDTO queryDTO, String userName);

ReagentMapper.xml

調用枚舉的?name()?方法獲取枚舉常量名稱字符串

    <!-- 通過狀態,查詢試劑列表 --><select id="selectByStatus" resultType="com.weiyu.pojo.Reagent">select<include refid="ReagentAllFields" />from Reagent<where><if test="queryDTO.reagentCategory != null and queryDTO.reagentCategory != ''">and rea_TypeName = #{queryDTO.reagentCategory}</if><if test="queryDTO.reagentName != null and queryDTO.reagentName != ''">and rea_Name like '%' + #{queryDTO.reagentName} + '%'</if><if test="queryDTO.status != null"><choose><!-- 常規 --><when test="queryDTO.status.name() == 'REGULAR'">and rea_State = 0 and rea_Amount > 0</when><!-- 少庫存 --><when test="queryDTO.status.name() == 'LESS_INVENTORY'">and rea_State = 0 and rea_Amount between 1 and 3</when><!-- 零庫存 --><when test="queryDTO.status.name() == 'ZERO_INVENTORY'">and rea_State = 0 and rea_Amount = 0</when><!-- 將過期 --><when test="queryDTO.status.name() == 'WILL_EXPIRE'">and rea_State = 0 and rea_Amount > 0 and rea_OverdueDate between dateadd(day, -1, getdate()) and dateadd(month, 1, getdate())</when><!-- 已過期 --><when test="queryDTO.status.name() == 'EXPIRED'">and rea_State = 0 and rea_Amount > 0 and rea_OverdueDate &lt; #{queryDTO.currentStartOfDay}</when><!-- 已注銷 --><when test="queryDTO.status.name() == 'LOGGED'">and rea_State = 1</when><!-- 全部 --></choose></if>and exists (select 1from Employeewhere emp_ID = #{userName}and emp_DeptID = rea_DeptID)</where></select>

在Java中,將枚舉變量從Mapper接口傳遞到MyBatis的XML文件時,MyBatis默認提供了兩種處理枚舉的方式,也可以通過自定義類型處理器實現更靈活的控制。以下是詳細步驟和示例:


方法1:使用MyBatis內置枚舉處理器(默認)

MyBatis默認使用EnumTypeHandler,將枚舉的名稱(name())作為字符串傳遞到XML。

示例代碼
  1. 枚舉定義

    java

    復制

    下載

    public enum UserStatus {ACTIVE, INACTIVE, PENDING
    }
  2. Mapper接口

    java

    復制

    下載

    public interface UserMapper {List<User> getUsersByStatus(@Param("status") UserStatus status);
    }
  3. XML映射文件

    xml

    復制

    下載

    運行

    <select id="getUsersByStatus" resultType="User">SELECT * FROM users WHERE status = #{status}<!-- 相當于 #{status, javaType=UserStatus} -->
    </select>
    • 實際執行的SQL:status = 'ACTIVE'(枚舉的字符串名稱)


方法2:使用枚舉序號(ordinal)

通過EnumOrdinalTypeHandler,將枚舉的序號(ordinal())作為整數傳遞。

步驟
  1. 全局配置(推薦在mybatis-config.xml中)

    xml

    復制

    下載

    運行

    <typeHandlers><typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.example.UserStatus"/> <!-- 替換為你的枚舉全限定名 -->
    </typeHandlers>
  2. 或局部配置(在XML中指定)

    xml

    復制

    下載

    運行

    <select id="getUsersByStatus" resultType="User">SELECT * FROM users WHERE status = #{status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>
    • 實際執行的SQL:status = 0(枚舉的序號值)


方法3:自定義類型處理器(推薦)

當需要存儲枚舉的自定義屬性(如數據庫中的編碼)時,需實現TypeHandler接口。

示例:將枚舉的自定義編碼存入數據庫
  1. 枚舉定義(添加自定義字段)

    java

    復制

    下載

    public enum UserStatus {ACTIVE("A"), INACTIVE("I"), PENDING("P");private final String code;UserStatus(String code) { this.code = code; }public String getCode() { return code; }
    }
  2. 自定義類型處理器

    java

    復制

    下載

    public class UserStatusTypeHandler implements TypeHandler<UserStatus> {@Overridepublic void setParameter(PreparedStatement ps, int i, UserStatus status, JdbcType jdbcType) throws SQLException {ps.setString(i, status.getCode()); // 存入枚舉的code值}@Overridepublic UserStatus getResult(ResultSet rs, String columnName) throws SQLException {String code = rs.getString(columnName);return Arrays.stream(UserStatus.values()).filter(s -> s.getCode().equals(code)).findFirst().orElse(null);}// 其他getResult方法實現類似...
    }
  3. 注冊類型處理器

    • 全局注冊(在mybatis-config.xml中)

      xml

      復制

      下載

      運行

      <typeHandlers><typeHandler handler="com.example.handler.UserStatusTypeHandler"/>
      </typeHandlers>
    • 或局部使用(在XML中指定)

      xml

      復制

      下載

      運行

      <select id="getUsersByStatus" resultType="User">SELECT * FROM users WHERE status = #{status, typeHandler=com.example.handler.UserStatusTypeHandler}
      </select>
  4. Mapper接口保持不變

    java

    復制

    下載

    List<User> getUsersByStatus(@Param("status") UserStatus status);

關鍵點總結

方法傳遞的值配置方式適用場景
默認EnumTypeHandler枚舉名稱(字符串)無需配置直接存儲枚舉名稱到VARCHAR列
EnumOrdinalTypeHandler枚舉序號(整數)全局配置或局部指定存儲序號到INT列
自定義TypeHandler任意自定義屬性實現接口并注冊復雜映射(如編碼轉換)

常見問題解決

  1. 枚舉傳遞后值為null

    • 檢查類型處理器是否匹配。

    • 確保XML中的參數名與@Param一致。

  2. 數據庫存的是整數但枚舉是字符串

    • 使用EnumOrdinalTypeHandler或自定義處理器。

  3. 自定義處理器不生效

    • 確認是否在mybatis-config.xml中全局注冊,或在XML中局部指定。

通過以上方法,你可以靈活地在MyBatis中處理枚舉類型的傳遞和映射。

在 MyBatis 的 XML 動態 SQL 中,直接使用?queryDTO.status == 'REGULAR'?這種寫法通常是不正確的,因為枚舉對象和字符串是不同類型。以下是正確做法和詳細解釋:

正確解決方案

1. 比較枚舉名稱(推薦)

xml

復制

下載

運行

<when test="queryDTO.status != null and queryDTO.status.name() == 'REGULAR'">AND user_type = 1
</when>
  • 原理:調用枚舉的?name()?方法獲取枚舉常量名稱字符串

  • 注意:需先檢查?queryDTO.status?是否為?null?避免 NPE

2. 直接比較枚舉常量(需全限定名)

xml

復制

下載

運行

<when test="queryDTO.status == @com.example.UserStatus@REGULAR">AND user_type = 1
</when>
  • 格式@包名.枚舉類名@枚舉常量

  • 缺點:路徑較長且硬編碼,修改枚舉位置時需要同步更新

3. 使用枚舉的 toString()(需重寫方法)

java

復制

下載

// 枚舉定義
public enum UserStatus {REGULAR("常規用戶");private final String desc;UserStatus(String desc) { this.desc = desc; }@Overridepublic String toString() { return this.desc; // 或 return this.name(); }
}

xml

復制

下載

運行

<when test="queryDTO.status != null and queryDTO.status.toString() == '常規用戶'">AND user_type = 1
</when>
  • 適用場景:需要比較自定義描述而非枚舉名稱時

  • 注意:默認?toString()?返回與?name()?相同,重寫可實現自定義邏輯


? 為什么不推薦直接比較字符串

xml

復制

下載

運行

<!-- 錯誤示例 -->
<when test="queryDTO.status == 'REGULAR'"> 
  • 類型不匹配:左側?queryDTO.status?是枚舉對象,右側?'REGULAR'?是字符串

  • 實際比較:相當于?enumObject.equals(String),永遠返回?false

  • OGNL 處理:MyBatis 使用 OGNL 表達式,不會自動轉換類型


最佳實踐總結

場景推薦寫法優點
比較枚舉常量名queryDTO.status.name() == 'REGULAR'直觀、無需修改枚舉定義
需要精確匹配枚舉實例queryDTO.status == @包名.UserStatus@REGULAR直接比較對象引用
比較枚舉的自定義描述queryDTO.status.toString() == '描述文本'支持業務友好文本
多條件判斷搭配?<choose>?使用枚舉 name()清晰易維護

完整示例

xml

復制

下載

運行

<select id="searchUsers" resultType="User">SELECT * FROM users<where><choose><when test="queryDTO.status != null and queryDTO.status.name() == 'REGULAR'">AND user_type = 1</when><when test="queryDTO.status != null and queryDTO.status.name() == 'VIP'">AND user_type = 2</when><otherwise>AND user_type IS NOT NULL</otherwise></choose></where>
</select>

重要提醒

  1. 空值檢查:始終優先判斷?queryDTO.status != null

  2. 大小寫敏感name()?返回的枚舉名稱是大小寫敏感的

  3. 避免魔法值:考慮使用常量替代硬編碼字符串

    xml

    復制

    下載

    運行

    <when test="queryDTO.status.name() == T(com.example.Constants).USER_REGULAR">

根據你的實際需求,推薦使用?枚舉.name() == '常量名'?的方式,兼具可讀性和類型安全性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85337.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85337.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85337.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為云Flexus+DeepSeek征文 | 華為云CCE容器高可用部署Dify高可用版實測:從0到1的高可靠應用實踐

引言 隨著大語言模型&#xff08;LLM&#xff09;技術的爆發&#xff0c;如何快速構建具備高可用、彈性擴展能力的AI應用開發平臺&#xff0c;成為企業數字化轉型的關鍵命題。華為云依托其云原生基礎設施&#xff0c;推出CCE容器高可用版Dify部署方案&#xff0c;通過“一鍵部…

c++_cout的理解和使用

問題引入 cout << (uf.is_same_set(x, y)) ? Y : N<<endl; 請問大家&#xff0c;這條語句對嗎&#xff1f;&#xff08;這里的uf.is_same_set(x, y)是一個自定義函數&#xff0c;返回bool值&#xff1b;所以不是問題的關鍵&#xff09;》 答案是這條語句報錯了…

山東大學項目實訓-創新實訓-法律文書專家系統-項目報告(八)

項目實訓博客 : 項目后端架構 , 項目的四端交互(前端 ,后端 ,模型端 ,數據庫)的開發和維護 , 項目功能總覽 作為項目的后端和前端交互功能主要開發者,我需要對項目的四端交互進行開發和維護. 總覽: 整體項目結構如圖所示: 前后端的交互: 前端封裝了request.js : 方便前端…

12.8Java Swing 中的MVC

在 Java Swing 中&#xff0c;MVC 模式被廣泛應用。例如&#xff0c;JTable、JList 等組件都采用了這種模式。通常&#xff1a; 模型&#xff1a;實現特定的 Swing 模型接口&#xff08;如 TableModel、ListModel&#xff09;。視圖&#xff1a;是 Swing 組件本身&#xff08;…

DDS(Data Distribution Service)

DDS&#xff08;Data Distribution Service&#xff09;是一種以數據為中心的發布/訂閱&#xff08;DCPS&#xff09;通信中間件協議棧標準&#xff08;由OMG組織維護&#xff09;。它專為高性能、可預測、實時、可靠的分布式系統設計&#xff0c;廣泛應用于國防、航空航天、工…

python爬蟲關于多進程,多線程,協程的使用

簡介&#xff1a; python其實沒有真正意義的多線程&#xff0c;因為有GIL鎖存在&#xff0c;但是python3.13去掉GIL鎖&#xff0c;有兩個版本&#xff0c;python3.13t和python3.13&#xff0c;python3.13去掉GIL鎖相當于python底層大規模改變&#xff0c;肯定會影響一些庫的使…

java 設計模式_行為型_23狀態模式

23.狀態模式 Java中的狀態設計模式是一種軟件設計模式&#xff0c;當對象的內部狀態更改時&#xff0c;該模式允許對象更改其行為。狀態設計模式通常用于以下情況&#xff1a;對象取決于其狀態&#xff0c;并且在運行期間必須根據其內部狀態更改其行為。狀態設計模式是許多行為…

Flink CDC MySQL 時區相差 8 小時問題優雅解決方式

Flink CDC MySQL 時區相差 8 小時問題解析 代碼運行環境 Flink 1.15 + FlinkCDC 2.4.0 + jdk1.8 +springboot 2.31、原因分析 Flink CDC 底層使用 Debezium 連接器來捕獲 MySQL 的數據變更,而 Debezium 在解析 MySQL 的 binlog 日志時,默認使用 UTC 時區來處理時間字段。若…

如何在 MX Linux 上安裝 Blender CAD 軟件

Blender 是一款免費且開源的 CAD 軟件,可用于 3D 動畫、建模、動態圖形、紋理處理、電腦游戲、UV 展開等。同時它也是一款專業的開源程序,是商業軟件(如 Maya 或 Cinema 4D)的替代品,支持導入或導出標準格式,如 OBJ、FBX、3DS、PLY 和 STL。Blender 還可以作為視頻編輯軟…

電腦上的.ssh目錄只做什么的

.ssh 目錄的作用和來源 系統自動創建 這個目錄是在你第一次使用SSH相關功能時自動創建的比如第一次執行 ssh 命令連接服務器時或者使用Git通過SSH協議克隆代碼時 主要用途 SSH密鑰存儲 - 存放公鑰/私鑰對已知主機記錄 - known_hosts 文件記錄你連接過的服務器指紋SSH客戶端…

Excel大廠自動化報表實戰(互聯網金融-數據分析周報制作下)

這是Excel大廠自動化報表實戰第四期--互聯網金融-數據分析周報制作下 數據資源已經與這篇博客捆綁&#xff0c;有需要者可以下載通過網盤分享的文件&#xff1a;2.4自動化報表-8月成交數據.xlsx&#xff0c;2.4自動化報表-8月獲客數據.csv等2個文件 鏈接: https://pan.baidu.c…

界面組件DevExpress WPF中文教程:Grid - 節點(Nodes)概述

DevExpress WPF擁有120個控件和庫&#xff0c;將幫助您交付滿足甚至超出企業需求的高性能業務應用程序。通過DevExpress WPF能創建有著強大互動功能的XAML基礎應用程序&#xff0c;這些應用程序專注于當代客戶的需求和構建未來新一代支持觸摸的解決方案。 無論是Office辦公軟件…

開源統一數據庫管理平臺完全指南:私有化部署方案與技術解析

摘要:面對MySQL、Oracle、Redis等混合數據庫環境,如何實現統一管控?本文深度評測5大開源平臺,附私有化部署方案和性能對比。 一、核心需求場景與技術選型 典型痛點: #mermaid-svg-LuCYYyJjBakpzzFH {font-family:"trebuchet ms",verdana,arial,sans-serif;font…

hot100 -- 14.貪心算法

1.買賣股票的最佳時機 方法&#xff1a; def MaxProfit(prices):max_pro, min_num 0, float(inf)for num in prices:if num < min_num:min_num nummax_pro max(max_pro, num - min_num)return max_pro 2.跳躍游戲 問題&#xff1a; 給你一個非負整數數組 nums &#…

Celery+fastAPI/Flask實現高性能應用

本文在創作過程中借助 AI 工具輔助資料整理與內容優化。圖片來源網絡。 引言 大家好&#xff0c;我是沛哥兒。 在當今的軟件開發領域&#xff0c;異步任務處理和高效的 Web 開發框架是提升應用性能和可擴展性的關鍵因素。Celery 作為一個強大的分布式任務隊列系統&#xff0c;…

【音視頻】PJSIP庫——pjsua命令使用詳解

1、源碼編譯 1)安裝依賴庫 sudo apt install libsrtp2-dev sudo apt install libopus-dev alsa-tools libalsaplayer-dev ffmpeg libalsa* pulseaudio-module-jack sudo apt install jackd libjack-jackd2-dev libjack-dev libsdl2-dev libv4l-dev libavcodec-dev libavde…

Python實例題:圖片批量處理工具

目錄 Python實例題 題目 問題描述 解題思路 關鍵代碼框架 難點分析 Python實例題 題目 圖片批量處理工具 問題描述 開發一個 Python 工具&#xff0c;實現以下功能&#xff1a; 遍歷指定文件夾下的所有圖片文件&#xff08;支持常見格式如 jpg、png、webp&#xff0…

超圖superMap iObjects for Java的Jar使用中遇到的問題

一、 cannot open shared object file: No such file or directory 1. 問題 2. 解決方法 &#xff08;1&#xff09;檢查有沒有配置環境變量 PATH &#xff08;2&#xff09;創建軟連接 ln -s &#xff08;3&#xff09;將主機 /usr/lib64 目錄中的libgomp.so.1 復制到 /pla…

常見的藍牙5.0抗干擾技術和算法

常見的藍牙5.0抗干擾技術和算法&#xff1a; 跳頻擴頻&#xff08;Frequency Hopping Spread Spectrum, FHSS&#xff09; 通過在不同的頻率通道上快速切換數據傳輸&#xff0c;減少與固定頻率干擾源的沖突。 直接序列擴頻&#xff08;Direct Sequence Spread Spectrum, DSSS&…

牛客與Moka深化合作,升級AI面試對接,引領招聘變革

近日&#xff0c;AI 招聘平臺牛客與國內領先的人力資源全模塊平臺 Moka 宣布完成 AI 面試產品的全新對接升級。此次升級實現了從 Moka 到牛客的一鍵互綁&#xff0c;并打通了簡歷出題、風險點提問、優勢技能挖掘等核心功能&#xff0c;為企業提供更加高效智能的面試體驗。 這一…