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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;为企业提供更加高效智能的面试体验。 这一…