java.lang.IllegalArgumentException: No enum constant found(Java.lang.IlLegalArgumentException:未找到枚举常量)
问题描述
我有此枚举,我要使用它来设置不同的状态:
@Enumerated(EnumType.STRING)
@Column(name = "status", length = 20)
private OnboardingTaskStatus status;
public enum OnboardingTaskStatus {
NEW,
IN_PROGRESS,
DISABLED,
}
当我尝试构建搜索规范时,我得到的结果是:
public Page<OnboardingTaskDto> findOnboardingTasks(OnboardingTaskSearchParams params, Pageable pageable){
Specification<OnboardingTasks> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (params.getStatus() != null) {
predicates.add(cb.equal(root.get("status"), params.getStatus()));
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
};
return onboardingTasksService.findAll(spec, pageable).map(onboardingMapper::taskToTaskDTO);
}
@Getter
@Setter
public class OnboardingTaskSearchParams {
private String title;
private String status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
我尝试将状态更新到此字段:
predicates.add(cb.equal(root.get("status"), OnboardingTaskStatus.valueOf(params.getStatus())));
但我收到错误:
OnboardingTaskStatus.2769df0841;嵌套异常为java.lang.IlLegalArgumentException:no enum常量OnboardingTaskStatus.2769df0841]带有根本原因 Java.lang.IlLegalArgumentException:没有枚举常量OnboardingTaskStatus.2769df0841
您知道在未找到值的情况下实现Enum搜索而不引发错误的正确方法吗?
推荐答案
报告的错误表明您正在尝试将String
OnboardingTaskStatus.2769df0841
转换为未定义的OnboardingTaskStatus
枚举值。
请不要在如何处理错误的值上寻找解决办法,而是尝试找出为什么您一开始就获得了错误的值。使用正确的枚举值单独测试Specification
,看看它是否工作。如果是这样的话-我认为它可能会这样做-检查您用来为OnboardingTaskSearchParams
表单提供值的代码,并仔细检查status
参数的值,可能您正在以错误的方式迭代枚举,等等。可能不是,但也要确保您的status
列没有包含不正确的值-在以前的代码版本中手动插入...
此外,为了缓解该问题,我会尝试在搜索条件中直接定义您的枚举值,Spring将自动处理String
和枚举值之间的转换。
我的意思是,不要将status
定义为OnboardingTaskSearchParams
中的String
,只需将该字段定义为枚举:
@Getter
@Setter
public class OnboardingTaskSearchParams {
private String title;
private OnboardingTaskStatus status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
或者更好:
@Getter
@Setter
public class OnboardingTaskSearchParams {
private String title;
private List<OnboardingTaskStatus> statuses;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
并在Specification
中使用枚举:
public Page<OnboardingTaskDto> findOnboardingTasks(OnboardingTaskSearchParams params, Pageable pageable){
Specification<OnboardingTasks> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (params.getStatus() != null) {
predicates.add(cb.equal(root.get("status"), params.getStatus()));
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
};
return onboardingTasksService.findAll(spec, pageable).map(onboardingMapper::taskToTaskDTO);
}
或者,如果使用多个值作为搜索条件:
public Page<OnboardingTaskDto> findOnboardingTasks(OnboardingTaskSearchParams params, Pageable pageable){
Specification<OnboardingTasks> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
final List<OnboardingTaskStatus> statuses = params.getStatuses();
if (statuses != null && ! statuses.isEmpty()){
predicates.add(root.get("status").in(statuses));
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
};
return onboardingTasksService.findAll(spec, pageable).map(onboardingMapper::taskToTaskDTO);
}
必须确保在您的前端中为可能的OnboardingTaskStatus
枚举、NEW
、IN_PROGRESS
和DISABLED
在表单中提供了正确的值。
需要注意的是,如果您的表单被提交,并且在到达您的服务或数据库相关代码之前发现任何不正确的枚举值,Spring将立即在Web层投诉。
如果您确实需要检查枚举值是否存在,并且仍然在搜索条件中使用String
表示status
,则您有多个选择。
例如,您可以在Commons-lang库的EnumUtils
类中使用isValidEnum
方法:
if(EnumUtils.isValidEnum(OnboardingTaskStatus.class, params.getStatus())){
predicates.add(
cb.equal(
root.get("status"),
OnboardingTaskStatus.valueOf(params.getStatus())
)
);
}
您可以使用Guava的Enums
类中的getIfPresent
方法:
Optional<OnboardingTaskStatus> optStatus = Enums.getIfPresent(OnboardingTaskStatus.class, params.getStatus());
if(optStatus.isPresent()){
predicates.add(
cb.equal(
root.get("status"),
OnboardingTaskStatus.valueOf(optStatus.get())
)
);
}
这个SO question提供了Jon Skeet和其他人的几个替代方案。
在Java 8中,您也有几个选项。除了其他答案中提供的答案外,您还可以尝试:
Optional<OnboardingTaskStatus> optStatus = EnumSet.allOf(OnboardingTaskStatus.class)
.stream()
.filter(e -> e.name().equals(params.getStatus()))
.findAny();
if(optStatus.isPresent()){
predicates.add(
cb.equal(
root.get("status"),
OnboardingTaskStatus.valueOf(optStatus.get())
)
);
}
最后,您似乎在幕后使用某种转换机制将status
String
转换为Specification
中相应的枚举值;相反,您可以签入Hibernate source code,该行将引发不同的错误:
predicates.add(cb.equal(root.get("status"), params.getStatus()));
类似:
Parameter value ... did not match expected type ...
如果是这样的话,请也复习一下这个逻辑,也许问题就在那里。
这篇关于Java.lang.IlLegalArgumentException:未找到枚举常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!