Java lambda 即使在第二次调用时也保留第一次调用的外部参数值

Java lambda keeps outer param value of first call even on second call

标题可能描述性不强,但我会尝试恢复我的问题。

因此,我正在尝试使用 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;
}

奇怪的是,当我为两个不同的过滤器 object 调用此代码时,lambda 似乎只使用一个 input 值,而它 returns 我只是一个查询对于第一个标准。这一定是与 java lambda 参数相关的问题,但我不能确切地说出它是什么。

真实场景:

当我有两个不同的过滤器时 object: { "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()); 被第一个过滤器调用两次 object

等待解决方案和解释为什么会这样。

Specificiation.and() returns 一个新的 Specification 因此您加入规范的代码不起作用。

您需要加入这样的规范:

    Specification<TrafficData> specification = Specification.where(specificationList.remove(0));

    return specificationList.stream().reduce(specification, Specification::and);