文章目录
- 前言
- 一、Enum定义
- 1.完整代码
- 2.分段解析
- 1.状态定义
- 2.状态内部变量定义
- 3.构造函数
- 4.重写getValue
- 5.fromCode
- tips
- 二、业务使用
- 完整业务函数
- fromCode() 使用
- getValue()使用
- 序列化和反序列化
- 总结
前言
Enum枚举类型安全、自带描述、支持 Mybatis 自动持久化、规范,是正式业务的首选,本文简单介绍了mybatisplus中Enum的使用,详细代码在代码仓库,如果只关注Enum使用,看common/OrderStatus.java(枚举定义核心类),dto/UpdateOrderStatusRequest.java(前端参数传递),service/OrderService.java(订单业务类,看里面的updateOrderStatus函数)
一、Enum定义
1.完整代码
packagecom.example.restaurantai.common;importcom.baomidou.mybatisplus.annotation.IEnum;importcom.fasterxml.jackson.annotation.JsonCreator;importcom.fasterxml.jackson.annotation.JsonValue;importlombok.Getter;/** * 序列化 就是把内存里的 Java 对象"翻译"成能传输/存储的格式(比如 JSON 字符串)。 * * 反序列化 就是反过来,把 JSON 字符串"翻译"回 Java 对象。 */@GetterpublicenumOrderStatusimplementsIEnum<Integer>{//定义枚举PENDING(1,"待处理"),PAID(2,"已支付"),CANCELLED(3,"已取消"),COMPLETED(4,"已完成");//定义枚举内部变量privatefinalIntegercode;privatefinalStringdesc;//构造函数OrderStatus(Integercode,Stringdesc){this.code=code;this.desc=desc;}//重写getValue方法@Override@JsonValue//序列化,java->json 输出数字1234 装箱 后端 -> 前端publicIntegergetValue(){returnthis.code;}@JsonCreator//反序列化 json->java 如2->paid 数字到枚举 拆箱 前端->后端publicstaticOrderStatusfromCode(Integercode){for(OrderStatusstatus:values()){if(status.code.equals(code)){returnstatus;}}thrownewIllegalArgumentException("未知订单状态码: "+code);}}2.分段解析
1.状态定义
//定义枚举PENDING(1,"待处理"),PAID(2,"已支付"),CANCELLED(3,"已取消"),COMPLETED(4,"已完成");你需要多少状态就在这里定义多少个变量
2.状态内部变量定义
//定义枚举内部变量privatefinalIntegercode;privatefinalStringdesc;这里定义状态内部需要的东西,一般一个数字做持久化,一个字符串用来展示在前端就够了
3.构造函数
//构造函数OrderStatus(Integercode,Stringdesc){this.code=code;this.desc=desc;}4.重写getValue
//重写getValue方法@Override@JsonValuepublicIntegergetValue(){returnthis.code;}mybatisplus要求使用了IEnum就必须重写其中的getValue方法,其实就是根据枚举变量输出它代表的数字,方便传输。常用使用方式如下写入数据库时自动调用
伪代码表示如下
// Service 代码orderInfo.setStatus(OrderStatus.PAID);orderInfoMapper.updateById(orderInfo);// MyBatis-Plus 内部流程:// OrderStatus.PAID ──调用 getValue()──▶ Integer 2 ──写入──▶ order_info.status = 2序列化
加上@JsonValue注解后,
意思是:“把我序列化成 JSON 时,别输出整个对象,只输出 getValue() 的返回值”。也是spring自动调用
// Controller 返回 OrderVO,Spring 自动序列化// OrderVO.status = OrderStatus.PAID ──调用 getValue()──▶ JSON: { "status": 2 }5.fromCode
@JsonCreator//反序列化 json->java 如2->paid 数字到枚举 拆箱 前端->后端publicstaticOrderStatusfromCode(Integercode){for(OrderStatusstatus:values()){if(status.code.equals(code)){returnstatus;}}thrownewIllegalArgumentException("未知订单状态码: "+code);}fromCode方法作用一句话总结为:把数字转化为枚举类型。常见用法如下:
读数据库记录时
MyBatis-Plus 从数据库读取时自动调用,把数字转化为枚举
// order_info 表 status 字段值为 2// MyBatis-Plus 内部流程:// 数据库值 2 ──发现实体字段是 OrderStatus 类型──▶// 遍历 values() 逐个比对 getValue() → 匹配 PAID → OrderStatus.PAID// 注:MyBatis-Plus 实际走的是 IEnum 接口 + 反射,// 不直接调 fromCode(),但逻辑等价反序列化
加上@JsonCreator注解后,前端传 JSON 时自动调用,数字->枚举
// 前端 PUT /api/orders/1/status Body: { "status": 2 }// Spring + Jackson 内部流程:// 1. 解析 JSON,拿到 status 的值是整数 2// 2. 发现目标字段类型是 OrderStatus,整数不匹配// 3. 查找 OrderStatus 上有 @JsonCreator 标记的静态方法// 4. 调用 OrderStatus.fromCode(2) → 返回 OrderStatus.PAID// 5. request.setStatus(OrderStatus.PAID)tips
对于getValue和fromCode,简单来说就是出去用 getValue ,进来用 fromCode
| 方法 | 方向 | 谁调 | 做什么 |
|---|---|---|---|
| getValue() | 枚举 → 数字 | MyBatis-Plus 写入 / Jackson 序列化 / 手动调用 | 把 PAID 变成 2 |
| fromCode() | 数字 → 枚举 | Jackson 反序列化 / 手动调用 | 把 2 变成 PAID |
二、业务使用
以简单订单业务流转为例
完整业务函数
/** * 订单状态流转 * PENDING → PAID * PENDING → CANCELLED * PAID → COMPLETED */publicbooleanupdateOrderStatus(Longid,OrderStatusstatus){OrderInfoorderInfo=orderInfoMapper.selectById(id);if(orderInfo==null){thrownewBusinessException("订单号不存在");}OrderStatusnow=orderInfo.getStatus();if(now==OrderStatus.PENDING&&status==OrderStatus.PAID){orderInfo.setStatus(OrderStatus.PAID);}elseif(now==OrderStatus.PENDING&&status==OrderStatus.CANCELLED){orderInfo.setStatus(OrderStatus.CANCELLED);}elseif(now==OrderStatus.PAID&&status==OrderStatus.COMPLETED){orderInfo.setStatus(OrderStatus.COMPLETED);}else{thrownewBusinessException("订单状态流转不合理");}returnorderInfoMapper.updateById(orderInfo)>0;}fromCode() 使用
查询隐式调用,自动完成从2->PAID的转换
OrderInfoorderInfo=orderInfoMapper.selectById(id);// ← 从数据库读出 status=2OrderStatusnow=orderInfo.getStatus();// ← 已经是 OrderStatus.PAIDgetValue()使用
更新时隐式调用,PAID->2
orderInfo.setStatus(OrderStatus.PAID);// 内存中是枚举对象orderInfoMapper.updateById(orderInfo);// ← 这里 MyBatis-Plus 内部调用 getValue()序列化和反序列化
对于序列化和反序列化的调用,在controller里面,接收前端数据,反序列化,2->PAID,返回VO,序列化,PAID->2
总结
业务代码全是 OrderStatus 枚举直接比较和赋值,看起来很干净——这正是 @JsonValue / @JsonCreator / IEnum 组合的价值: 把序列化/反序列化的脏活藏在底层,业务层只和枚举打交道 。