MyBatis 如何映射 Enum(使用 EnumTypeHandler、自定义 TypeHandler)

文章目录

  • 1. MyBatis 中的 Enum 映射概述
  • 2. 使用 EnumTypeHandler
    • 2.1 代码示例:将 Enum 映射为字符串
    • 2.2 代码示例:将 Enum 映射为整数
    • 2.3 如何配置 EnumTypeHandler
  • 3. 自定义 TypeHandler
    • 3.1 为什么需要自定义 TypeHandler
    • 3.2 自定义 TypeHandler 的实现
    • 3.3 如何注册自定义 TypeHandler
  • 4. 注意事项
  • 5. 总结

在现代 Java 开发中, Enum(枚举)作为一种定义有限集合常量的类型,被广泛用于表示状态、类型或配置选项。作为 Java 开发中的主流 ORM 框架之一,MyBatis 为 Enum 提供了内置的支持,并允许开发者通过自定义 TypeHandler 来实现更复杂的映射逻辑。本篇博客将深入讨论 MyBatis 如何处理 Java 枚举类型的映射,重点介绍 EnumTypeHandler 和自定义 TypeHandler 的实现。

前置博客:Java中枚举是什么?枚举(Enumeration, 简称 Enum)是 Java 中一种特殊的数据类型,用于定义一组常量。它提供了一种更具语义的方式来表示和处理固定集合的值,避免了魔法数字或字符串。


1. MyBatis 中的 Enum 映射概述

Enum 的概念

在 Java 中,Enum 是一种特殊的类,用于定义常量集合。每个 Enum 实例都是该类的一个常量,具备固定的值和方法。

public enum Status {ACTIVE, INACTIVE, DELETED;
}

为什么需要在 MyBatis 中处理 Enum

ORM(对象关系映射)框架的核心目标是将数据库中的关系模型映射到 Java 对象。然而,数据库中的字段通常使用整数或字符串类型来表示状态或类型,而在 Java 代码中,我们常常使用 Enum 来提高代码的可读性和可维护性。因此,如何将 Enum 与数据库字段映射,是 MyBatis 中不可避免的问题。

Enum 映射在数据库设计中的意义

枚举类型通常用于表示有限集合的状态或分类。例如,数据库中一个状态字段可能以整数 1 表示“激活”,0 表示“禁用”。而在 Java 代码中,我们更希望通过 Enum(如 Status.ACTIVEStatus.INACTIVE)来处理这些状态。


2. 使用 EnumTypeHandler

MyBatis 自带了 EnumTypeHandler,用于将 Java 枚举类型映射到数据库字段。这个处理器可以自动将 Enum 类型与数据库字段进行映射,无需开发者编写额外的处理逻辑。

EnumTypeHandler 映射整数与字符串

EnumTypeHandler 支持两种映射方式:

  • Enumname() 方法返回的字符串值映射到数据库的 VARCHAR 字段。
  • Enumordinal() 值(枚举项的顺序,从 0 开始)映射到数据库的整数字段。

2.1 代码示例:将 Enum 映射为字符串

以下是将 Status 枚举映射为数据库中 VARCHAR 字段的例子:

public enum Status {ACTIVE, INACTIVE, DELETED;
}

在 MyBatis 的映射文件中,我们可以这样配置:

<select id="selectStatusById" resultType="Status">SELECT status FROM users WHERE id = #{id}
</select>

当数据库中存储的值为 "ACTIVE" 时,MyBatis 会将其映射为 Status.ACTIVE

2.2 代码示例:将 Enum 映射为整数

如果数据库中存储的 status 是整数类型(例如:0 表示 ACTIVE1 表示 INACTIVE),则 MyBatis 通过 ordinal() 方法实现:

<select id="selectStatusById" resultType="Status">SELECT status FROM users WHERE id = #{id}
</select>

需要注意的是,使用 ordinal() 存在风险,如果 Enum 发生改动(如插入新常量),可能导致映射出错。因此,更推荐使用字符串映射。

2.3 如何配置 EnumTypeHandler

EnumTypeHandler 是 MyBatis 的默认处理器,因此我们不需要额外配置。当需要自定义映射行为时,可以在 mybatis-config.xml 中显式声明:

<typeHandlers><typeHandler handler="org.apache.ibatis.type.EnumTypeHandler" javaType="com.example.Status"/>
</typeHandlers>

也可以通过注解方式:

@Result(property = "status", column = "status", typeHandler = EnumTypeHandler.class)

3. 自定义 TypeHandler

3.1 为什么需要自定义 TypeHandler

有时,MyBatis 默认的 EnumTypeHandler 无法满足项目中的特定需求。例如,数据库中的枚举字段可能需要映射为更复杂的类型,或者 Enum 映射的逻辑需要根据业务规则进行调整。在这种情况下,自定义 TypeHandler 是更灵活的选择。

3.2 自定义 TypeHandler 的实现

假设我们需要将 Status 枚举映射为数据库中的自定义值,如:

  • ACTIVE 映射为 "A"
  • INACTIVE 映射为 "I"
  • DELETED 映射为 "D"

我们可以创建自定义的 TypeHandler 来实现该映射逻辑:

public class StatusTypeHandler extends BaseTypeHandler<Status> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter == Status.ACTIVE ? "A" : parameter == Status.INACTIVE ? "I" : "D");}@Overridepublic Status getNullableResult(ResultSet rs, String columnName) throws SQLException {String status = rs.getString(columnName);return "A".equals(status) ? Status.ACTIVE : "I".equals(status) ? Status.INACTIVE : Status.DELETED;}@Overridepublic Status getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String status = rs.getString(columnIndex);return "A".equals(status) ? Status.ACTIVE : "I".equals(status) ? Status.INACTIVE : Status.DELETED;}@Overridepublic Status getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String status = cs.getString(columnIndex);return "A".equals(status) ? Status.ACTIVE : "I".equals(status) ? Status.INACTIVE : Status.DELETED;}
}

在自定义 TypeHandler 中,getNullableResult 方法被重载了三次,以处理不同的情况。这三种重载方法的主要作用是从数据库中提取枚举值,并根据不同的输入源(列名、列索引或存储过程的输出参数)进行相应的映射。以下是它们各自的用途:

  1. getNullableResult(ResultSet rs, String columnName)

    • 这个方法用于从 ResultSet 中通过列名获取枚举值。通常在 SQL 查询返回结果时,我们通过列名来提取数据。
    • 例如:如果查询结果中有一列名为 status,你可以通过 ResultSetgetString("status") 获取该列的值,并将其映射为枚举值。
  2. getNullableResult(ResultSet rs, int columnIndex)

    • 这个方法用于从 ResultSet 中通过列索引获取枚举值。列索引是指返回的结果集中列的顺序,从 1 开始。
    • 这种方式更高效,尤其当你知道具体列的位置时,避免了列名查找的开销。例如,使用 rs.getString(1) 来获取第一列的值并将其映射为枚举值。
  3. getNullableResult(CallableStatement cs, int columnIndex)

    • 这个方法用于处理从存储过程的输出参数中获取枚举值。CallableStatement 是用于调用存储过程的,存储过程有时会返回多个输出参数。该方法根据输出参数的索引获取值,并将其映射为枚举。
    • 例如,存储过程返回的 OUT 参数可以通过 CallableStatement 获取并映射为对应的枚举值。
  • 方法重载(overloading)是为了应对不同的数据获取方式:通过列名、列索引或存储过程的输出参数。
  • 这三种方式都可能在不同的场景中使用,因此 MyBatis 的 TypeHandler 提供了这些重载,以便开发者能灵活应对不同的数据库访问场景。

3.3 如何注册自定义 TypeHandler

在 MyBatis 配置中注册自定义 TypeHandler,可以通过以下方式:

<typeHandlers><typeHandler handler="com.example.StatusTypeHandler" javaType="com.example.Status"/>
</typeHandlers>

注册完成后,MyBatis 会在映射 Status 类型时自动使用 StatusTypeHandler


4. 注意事项

设计数据库字段类型

在设计数据库字段时,选择合适的数据类型至关重要。如果你的 Enum 很可能会随着业务需求的变化而增加新值,建议使用字符串存储枚举值,以避免使用整数时出现的顺序问题。

如何处理未知或新增的枚举值

当数据库中出现了 Java 枚举中不存在的值时,应该明确处理此类情况。可以通过在 TypeHandler 中添加默认值或抛出异常来处理不匹配的情况。


5. 总结

MyBatis 提供了多种映射枚举类型的方式,EnumTypeHandler 适合大多数情况,而自定义 TypeHandler 提供了更灵活的选项。开发者应根据项目的具体需求选择合适的映射策略,并确保 Enum 与数据库设计的一致性,以避免常见的问题。

通过代码示例和最佳实践的指导,我们可以更好地掌握如何在 MyBatis 中高效地处理枚举类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/57486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git提交到github个人记录

windows下git下载 1.进入git官网https://git-scm.com/downloads/win 一直默认选项即可 2.在settings中SSH and GPG keys中Add SSH key 3.选择git cmd git使用 1.配置用户名&#xff0c;和邮箱 git config --global user.email "youexample.com" git config --g…

Director3D: Real-world Camera Trajectory and 3DScene Generation from Text 论文解读

目录 一、概述 二、相关工作 1、文本到3D生成 2、3DGS 三、Director3D 1、Cinematographer 2、Decorator 3、Detailer 4、Loss 一、概述 该论文提出利用真实世界数据集&#xff0c;设计一个从文本生成真实世界3D场景和自适应相机轨迹的强大的开放世界文本到3D生成框架…

067_基于springboot的HSK学习平台

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

【进阶OpenCV】 (18)-- Dlib库 --人脸关键点定位

文章目录 人脸关键点定位一、作用二、原理三、代码实现1. 构造人脸检测器2. 载入模型&#xff08;加载预测器&#xff09;3. 获取关键点4. 显示图像5. 完整代码 总结 人脸关键点定位 在dlib库中&#xff0c;有shape_predictor_68_face_landmarks.dat预测器&#xff0c;这是一个…

安装vue发生异常: idealTree:nodejs: sill idealTree buildDeps

一、异常 C:\>npm install vue -g npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIREDnpm ERR! request to https://registry.npm.taobao.org/vue failed, reason: certificate has expired 二、原因 请求 https://registry.npm.taobao.org 失败&#xff0c;证…

Spring Boot与Flyway实现自动化数据库版本控制

一、为什么使用Flyway 最简单的一个项目是一个软件连接到一个数据库&#xff0c;但是大多数项目中我们不仅要处理我们开发环境的副本&#xff0c;还需要处理其他很多副本。例如&#xff1a;开发环境、测试环境、生产环境。想到数据库管理&#xff0c;我们立刻就能想到一系列问…

网站漏扫:守护网络安全的关键防线

网站漏洞扫描&#xff0c;简称漏扫&#xff0c;是一种针对网站进行漏洞检测的安全服务。网站漏洞扫描在网络安全中占据着至关重要的地位。 网站漏扫在及时发现和修复漏洞方面发挥着关键作用 通过对网站和系统的全面扫描&#xff0c;能够快速识别出各种潜在的漏洞&#xff0c;…

jmeter中发送post请求遇到的问题

用jmeter发送post请求&#xff0c;把请求参数放在Body Data处&#xff0c;参数都写得正确&#xff0c;但没想到结果每次都报错&#xff0c;直接响应结果乱七八糟&#xff0c;改成用Parameters,反而不乱报错了。 上图 请求里如下 另外一些请求也是这样 这个响应结果也是错误的…

【文献及模型、制图分享】长江中游经济区“水—能源—粮食”系统与城市绿色转型适配性研究

文献介绍 评价资源系统与城市绿色发展适配程度是判断城市健康程度的关键。通过构建“系统压力指数—优劣解距离法&#xff08;TOPSIS&#xff09;—脱钩弹性模型&#xff08;Tapio&#xff09;”评价体系&#xff0c;对2012—2021年长江中游经济区“水—能源—粮食”&#xff…

aws 把vpc残留删除干净

最近忘了把vpc 删干净导致又被收了冤大头钱 在删除vpc 的收发现又eni在使用&#xff0c;但是忘了是哪个资源在占用 先用命令行把占用的资源找出来停掉 使用 AWS 命令行界面&#xff08;CLI&#xff09;来查看 VPC 的使用情况 列出子网&#xff1a; aws ec2 describe-subnets …

项目管理必备!2024年Jira与禅道之间的秘密故事?

一、项目管理工具的重要性 在当今快节奏的工作环境中&#xff0c;项目管理软件的重要性愈发凸显。随着企业规模的不断扩大和业务的日益复杂&#xff0c;传统的项目管理方式已经难以满足需求。项目管理软件成为提升团队协作和工作效率的关键工具。 首先&#xff0c;项目管理软…

vue3项目页面实现echarts图表渐变色的动态配置

完整代码可点击vue3项目页面实现echarts图表渐变色的动态配置-星林社区 https://www.jl1mall.com/forum/PostDetail?postId202410151031000091552查看 一、背景 在开发可配置业务平台时&#xff0c;需要实现让用户对项目内echarts图表的动态配置&#xff0c;让用户脱离代码也…

计算机导论

概述 计算机简史 1935年代&#xff0c;英国数学家图灵(Alan Turing)提出“图灵机”&#xff0c;奠定了计算机的理论基础。 1952年&#xff0c;冯诺依曼确定了计算机由运算器、控制器、存储器、输入、输出等5部分组成&#xff08;Von Neumann 体系结构&#xff09;。 60年代…

k8s备份恢复(velero)

velero简介 velero官网&#xff1a; https://velero.io/ velero-github&#xff1a; https://github.com/vmware-tanzu/velero velero的特性 备份可以按集群资源的子集&#xff0c;按命名空间、资源类型标签选择器进行过滤&#xff0c;从而为备份和恢复的内容提供高度的灵活…

【含开题报告+文档+PPT+源码】基于SSM框架的诗词吟诵知识学习系统的设计与实现

开题报告 随着信息技术的迅猛发展和互联网的普及&#xff0c;在线教育逐渐成为现代教育的重要形式。在线学习平台以其便捷性、灵活性和个性化等特点&#xff0c;受到广大师生的青睐。特别是在线吟诵知识学习&#xff0c;已经成为许多学生提升自我修养、陶冶情操的重要途径。青…

Google DeepMind推出DemoStart自主强化学习方法 利用少量示范样本实现复杂操作任务

一直以来&#xff0c;研究人员都在试图开发出能够在现实环境中安全、高效地执行复杂任务&#xff08;如多指手操作&#xff09;的机器人技能。传统的机器人学习方法往往需要大量的实际数据&#xff0c;这不仅耗时耗力&#xff0c;还存在安全风险。因此&#xff0c;仿真环境下的…

Netty简单应用

1.服务端构建 接收客户端请求&#xff0c;打印请求消息&#xff1b;消息采用内置String作为编码与解码器&#xff1b;开启信息输入监听线程&#xff0c;发送消息至客户端&#xff1b; 1.1 服务端消息处理类 import io.netty.channel.Channel; import io.netty.channel.Chann…

双十一好物必买清单攻略,这几款双十一必入的宝藏好物分享

随着双十一购物节的脚步日益临近&#xff0c;无数消费者都在期待着在这个年度大促中抢购到自己心仪已久的好物&#xff0c;为了帮助大家更好地规划购物计划&#xff0c;精选出真正值得入手的宝藏产品&#xff0c;我们特别整理了这份双十一好物必买清单攻略&#xff0c;无论你是…

spring day1023

ok了家人们&#xff0c;今天继续学习spring框架&#xff0c; 七.Spring的注解开发 在开发中&#xff0c;配置文件中 Bean 标签会非常多&#xff0c;难以维护。怎么 办&#xff1f; 使用注解的形式替代 xml 配置&#xff0c;可以将一些繁杂的 spring 配置 从工程中消除掉&…

业余时间试一试利用AI 人工智能赚钱

内容创作与写作&#xff1a; 撰写文章&#xff1a;许多网站、博客和企业都需要大量的优质内容。利用 AI 工具如 ChatGPT 等&#xff0c;获取文章的思路、框架甚至初稿&#xff0c;然后根据自己的知识和经验进行修改、润色和完善。你可以在一些自由撰稿人平台、内容创作平台上承…