mybatisplus Enum枚举,@JsonValue / @JsonCreator简单使用

mybatisplus Enum枚举,@JsonValue / @JsonCreator简单使用

文章目录

  • 前言
  • 一、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.PAID

getValue()使用

更新时隐式调用,PAID->2

orderInfo.setStatus(OrderStatus.PAID);// 内存中是枚举对象orderInfoMapper.updateById(orderInfo);// ← 这里 MyBatis-Plus 内部调用 getValue()

序列化和反序列化

对于序列化和反序列化的调用,在controller里面,接收前端数据,反序列化,2->PAID,返回VO,序列化,PAID->2

总结

业务代码全是 OrderStatus 枚举直接比较和赋值,看起来很干净——这正是 @JsonValue / @JsonCreator / IEnum 组合的价值: 把序列化/反序列化的脏活藏在底层,业务层只和枚举打交道 。