【发布时间】:2022-01-06 11:13:57
【问题描述】:
标题可能不太具有描述性,但我会尝试继续我的问题。
所以,我正在尝试使用 Java 规范创建动态查询。在我的例子中,带有过滤器的 DTO 来自 REST 端点,对于每个过滤器,我都在尝试创建这样的规范:
private Specification<TrafficData> buildSpecificationQuery(TrafficDataRequestDTO requestDTO) {
List<Specification<TrafficData>> specificationList = new ArrayList<>();
requestDTO.getFilters().forEach(filter -> {
specificationList.add(createSpecification(filter));
});
Specification<TrafficData> specification = Specification.where(specificationList.remove(0));
specificationList.forEach(specification::and);
return specification;
}
private Specification<TrafficData> createSpecification(final TrafficDataFilterDTO input) {
switch (input.getOperator()) {
case EQUALS:
return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(input.getFieldName()), input.getValue());
case NOT_EQUALS:
return (root, query, criteriaBuilder) ->
criteriaBuilder.notEqual(root.get(input.getFieldName()), input.getValue());
case STARTS_WITH:
return (root, query, criteriaBuilder) ->
criteriaBuilder.like(root.get(input.getFieldName()), input.getValue() + "%");
case ENDS_WITH:
return (root, query, criteriaBuilder) ->
criteriaBuilder.like(root.get(input.getFieldName()), "%" + input.getValue());
case CONTAINS:
return (root, query, criteriaBuilder) ->
criteriaBuilder.like(root.get(input.getFieldName()), "%" + input.getValue() + "%");
default:
throw new RuntimeException("Operation not supported yet");
}
}
过滤器 DTO 如下所示:
@Data
public class TrafficDataFilterDTO {
private String fieldName;
private TrafficDataFilterOperator operator;
private String value;
}
奇怪的是,当我为两个不同的过滤器对象调用这段代码时,似乎 lambdas 只使用了一个 input 值,它只为第一个条件返回了一个查询。这可能是与 java lambda 参数有关的问题,但我无法确切地说出它是什么。
所以一个真实的场景:
当我有两个不同的过滤器对象时:
{ "fieldName": "version", "operator": "EQUALS", "value": "EN_UK" }, { "fieldName": "isManaged", "operator": "EQUALS", "value": true }
方法 createSpecification(final TrafficDataFilterDTO input) 被调用两次,输入值正确(对于每个过滤器),但包含 lambda 的行
criteriaBuilder.equal(root.get(input.getFieldName()), input.getValue()); 被第一个过滤器对象调用两次
等待解决方案和解释为什么会发生这种情况。
【问题讨论】:
-
"似乎 lambdas 只使用一个输入值,它只针对第一个条件返回一个查询" 为什么会这样?这似乎是一个 XY 问题。您是在告诉我们您认为原因是什么,而不是告诉我们根本的问题。什么不起作用?
-
注释不是代码的好地方。如果您认为可以澄清您的问题,请编辑问题。
-
当我有两个不同的过滤器对象时:``` { "fieldName": "version", "operator": "EQUALS", "value": "EN_UK" }, { "fieldName": "isManaged", "operator": "EQUALS", "value": true } ``` 方法
createSpecification(final TrafficDataFilterDTO input)被调用两次,使用正确的input值(对于每个过滤器),但包含 lambda @ 的行987654328@ 使用第一个过滤器值调用两次 -
恕我直言,问题出在
specificationList.forEach(specification::and);-Specificiation.and()返回一个新的Specificiation但你忽略了它,最后只返回第一个创建的specification
标签: java lambda criteria-api