Spring Data JPA Specification枚举查询报No enum constant如何修复
问题修复方案
错误根因
- 枚举反序列化失败:请求传入的status参数值不是
BusinessCustomersStatus枚举定义的名称(A/O/N/V/S/I),本次传入了无效字符串4d29e059cf,Spring MVC默认按枚举name属性做反序列化,找不到对应枚举实例就抛出该异常。 - 查询逻辑冗余错误:代码中
e.name().equals(params.getStatus())逻辑是拿单个枚举的名称和List<BusinessCustomersStatus>类型的参数做相等比较,永远返回false,这段校验逻辑完全无效。
修复步骤
1. 修复枚举参数反序列化逻辑
两种可选实现方案:
- 方案A:要求请求方传入枚举的name值(A/O/N/V/S/I),不要传入
active这类自定义status字段值,也不要传入无效字符串。 - 方案B:自定义枚举反序列化器,支持按自定义的status字段值反序列化,代码示例如下:
// 给枚举类新增工具方法 public enum BusinessCustomersStatus { A("active"), O("onboarding"), N("not_verified"), V("verified"), S("suspended"), I("inactive"); private String status; BusinessCustomersStatus(String status) { this.status = status; } public String getStatus() { return status; } // 根据status值匹配对应枚举 public static Optional<BusinessCustomersStatus> of(String status) { return Arrays.stream(BusinessCustomersStatus.values()) .filter(e -> e.getStatus().equalsIgnoreCase(status.trim())) .findFirst(); } } // 自定义枚举反序列化器 public class BusinessCustomersStatusDeserializer extends StdDeserializer<BusinessCustomersStatus> { public BusinessCustomersStatusDeserializer() { super(BusinessCustomersStatus.class); } @Override public BusinessCustomersStatus deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String value = p.getText(); return BusinessCustomersStatus.of(value) .orElseThrow(() -> new IllegalArgumentException("无效的客户状态值:" + value)); } } // 给DTO字段绑定反序列化器 @Getter @Setter public class BusinessCustomersSearchParams { private String title; @JsonDeserialize(using = BusinessCustomersStatusDeserializer.class) private List<BusinessCustomersStatus> status; private LocalDateTime createdAt; private LocalDateTime updatedAt; }
2. 修复查询Specification逻辑
删掉无效的枚举校验代码,直接判断status列表非空后添加in查询条件,修复后代码如下:
public Page<BusinessCustomersFullDTO> findBusinessCustomers(BusinessCustomersSearchParams params, Pageable pageable) { Specification<BusinessCustomers> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); if (params.getTitle() != null) { predicates.add(cb.like(cb.lower(root.get("title")), "%" + params.getTitle().toLowerCase() + "%")); } List<BusinessCustomersStatus> statuses = params.getStatus(); if (statuses != null && !statuses.isEmpty()) { predicates.add(root.get("status").in(statuses)); } return cb.and(predicates.toArray(new Predicate[0])); }; return businessCustomersService.findAll(spec, pageable).map(businessCustomersMapper::toFullDTO); }
可选优化
可添加全局异常处理器捕获枚举反序列化异常,返回友好的业务错误提示,避免直接暴露堆栈信息给前端。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

