遇到数组值参数绑定,但期望 [java.lang.String (n/a)]

问题描述 投票:0回答:1

我需要根据传递的参数动态生成查询,并且需要连接三个表,在使用 EntityManager CriteriaBuilder 构建查询时遇到异常,如果我将其转换为 Criteria,则相同的代码结构可以工作,但我只想使用 CriteriaBuilder。

        @Override
    @Transactional
    public List<DatapointReply> getAllByFilter(Map<String, List<Object>> filter, int maxResults,
            boolean matchAllFilters) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<DatapointReply> criteriaQuery = criteriaBuilder.createQuery(DatapointReply.class);
        Root<PartDatapointReply> datapointReplyRoot = criteriaQuery.from(PartDatapointReply.class);
        Join<DatapointReply, Datapoint> datapointJoin = null;
        Join<PartDatapointReply, Part> partJoin = null;
        criteriaQuery.select(datapointReplyRoot);
        if (filter.containsKey("datapointkey")) {
            datapointJoin = datapointReplyRoot.join("datapoint");
        }
        if (filter.containsKey("partstatus") || filter.containsKey("partmodelnumber")) {
            partJoin = datapointReplyRoot.join("part");
        }

        List<Predicate> predicateList = new ArrayList<>();
        for (String searchKey : filter.keySet()) {
            List<Object> searchTerms = filter.get(searchKey);
            Predicate predicate = buildSearchCriterion(new String[searchTerms.size()], true, JunctionType.OR, datapointReplyRoot, criteriaBuilder,
                    "value");
            if (predicate != null) {
                predicateList.add(predicate);
            }
        }

        Predicate[] predicateArray = predicateList.toArray(new Predicate[predicateList.size()]);
        if (!predicateList.isEmpty() && matchAllFilters) {
            criteriaBuilder.and(predicateArray);
        } else if (!predicateList.isEmpty() && !matchAllFilters) {
            criteriaBuilder.or(predicateArray);
        }

        TypedQuery<DatapointReply> query = entityManager.createQuery(criteriaQuery);
        // Define the Max Results
        if (maxResults > SearchEngine.SEARCH_MAX_RESULTS_ALL) {
            query.setMaxResults(maxResults);
        }
        return query.getResultList();
    }


// Get Predicate based on parameter
private Predicate buildSearchCriterion(String[] values, boolean isWildcardSearch, JunctionType criteriaType,
            Root<PartDatapointReply> datapointReplyRoot, CriteriaBuilder criteriaBuilder, String... attributeNames) {

        // Build the Search Criteria as Single or Multiple Column Search
        Predicate finalCriterion = null;

        if (!isWildcardSearch) {

            List<Predicate> criteria = new ArrayList<>();
            for (String attributeName : attributeNames) {
                Predicate attributeCriterion = criteriaBuilder.in(datapointReplyRoot.get(attributeName)).value(values);
                criteria.add(attributeCriterion);
            }
            if (criteriaType == null || criteriaType == JunctionType.OR) {
                finalCriterion = criteriaBuilder.or(criteria.toArray(new Predicate[criteria.size()]));
            } else {
                finalCriterion = criteriaBuilder.and(criteria.toArray(new Predicate[criteria.size()]));
            }
        } else if (isWildcardSearch) {
            // Wildcard OR search on a single attribute
            // Search through each Search Term, ignoring white space, and add
            // each term to the Criteria Restrictions.

            List<Predicate> criteria = new ArrayList<>();
            for (String attributeName : attributeNames) {
                List<Predicate> attributeCriteria = new ArrayList<>();
                Predicate attributeCriterion;
                for (String value : values) {
                    Predicate valueCriterion;
                    // Wrap the Value in Wild Cards if it is a Wild Card Search
                    if (isWildcardSearch) {
                        value = "%" + value + "%";
                    }
                    valueCriterion = criteriaBuilder.like(criteriaBuilder.lower(datapointReplyRoot.get(attributeName)), value.toLowerCase());
                    attributeCriteria.add(valueCriterion);
                }
                attributeCriterion = criteriaBuilder.or(attributeCriteria.toArray(new Predicate[attributeCriteria.size()]));
                criteria.add(attributeCriterion);
            }
            if (criteriaType == null || criteriaType == JunctionType.OR) {
                finalCriterion = criteriaBuilder.or(criteria.toArray(new Predicate[criteria.size()]));
            } else {
                finalCriterion = criteriaBuilder.and(criteria.toArray(new Predicate[criteria.size()]));
            }
        }
        return finalCriterion;
    }

收到以下错误消息:

java.lang.IllegalArgumentException: Encountered array-valued parameter binding, but was expecting [java.lang.String (n/a)]
    at org.hibernate.query.spi.QueryParameterBindingValidator.validateArrayValuedParameterBinding(QueryParameterBindingValidator.java:142) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:49) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:27) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at ```
jpa jpa-2.0 entitymanager hibernate-criteria hibernate-5.x
1个回答
14
投票

将下面几行中的值类型从

String[]
更改为
Arrays.asList(values)
将解决问题。

Predicate attributeCriterion = criteriaBuilder.in(
    datapointReplyRoot.get(attributeName)).value(Arrays.asList(values)
);
© www.soinside.com 2019 - 2024. All rights reserved.