jpa - 遇到数组值参数绑定,但期待 [java.lang.String (n/a)]
问题描述
我需要根据传递的参数动态生成一个查询,并且需要加入三个表,在使用 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 ```
解决方案
在下面的行中将值的类型从 String[] 更改为 Arrays.asList(values) 将解决问题。
谓词 attributeCriterion = criteriaBuilder.in(datapointReplyRoot.get(attributeName)).value(Arrays.asList(values));
推荐阅读
- angular - 如何等待外部 observable 发出一个值,然后在订阅另一个 observable 之前检查条件?
- linux - 如何使用 sed 命令更改 limits.conf 中的 ulimit 值?
- series - 如何按熊猫系列的多列分组
- reactor-netty - reactor.ipc.netty.tcp.TcpServer 和 reactor.netty.tcp.TcpServer 有什么区别?
- android - Android:监听互联网连接变化并在 webView 中加载 URL On connected
- php - WSGI 的行为是动态的吗?
- php - 如何显示具有相同ID php的多个值
- excel - 在 Excel VBA 中使用 MSXML2 进行 Cookie 身份验证
- c++ - pc和Arduino之间通过USB进行串行通信
- python - 在获取 url python 中将数据框列值作为参数传递