[英]JPA Criteria dynamic predicate creation
First of all, I'm new to JPA, especially to the criteria API, so it might be something very basic that I do wrong. 首先,我是JPA的新手,尤其是对于标准API,因此我做错了可能是非常基本的事情。
I'm trying to select some Items from the database. 我正在尝试从数据库中选择一些项目。 I want to implement pagination, so in the future I'll need to reuse the predicate in a method that returns with the number of objects.
我想实现分页,因此将来我将需要在返回带有对象数量的方法中重用谓词。 For now, I want to separate the building of the predicate from the actual query execution.
现在,我想将谓词的构建与实际查询执行分开。 I came up with the following two methods:
我想出了以下两种方法:
private Predicate assemblePredicateBasedOnParameters(Map<String, String> parameterMap, Root<Item> item){
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
Predicate predicate = cb.conjunction();
for(String parameter : parameterMap.keySet()){
String value = parameterMap.get(parameter);
if(parameter.equals(FilteringKeyword.NAME.toString()))
{
Predicate newPredicate = cb.like(item.<String>get(FilteringKeyword.NAME.toString()), "%"+value+"%");
predicate = cb.and(predicate, newPredicate);
}
else if(parameter.equals(FilteringKeyword.DESCRIPTION.toString())){
Predicate newPredicate = cb.like(item.<String>get(FilteringKeyword.DESCRIPTION.toString()), "%"+value+"%");
predicate = cb.and(predicate, newPredicate);
}
else if(parameter.equals(FilteringKeyword.MINPRICE.toString())){
Predicate newPredicate = cb.ge(item.<Integer>get("startingPrice"), Integer.parseInt(value));
predicate = cb.and(predicate, newPredicate);
}
else if(parameter.equals(FilteringKeyword.MAXPRICE.toString()) && Integer.parseInt(value)>0){
Predicate newPredicate = cb.le(item.<Integer>get("startingPrice"), Integer.parseInt(value));
predicate = cb.and(predicate, newPredicate);
}
}
return predicate;
}
@Override
public List<Item> getItems(Map<String, String> parameterMap, int from, int to) {
CriteriaQuery<Item> query = entityManager.getCriteriaBuilder().createQuery(Item.class);
query.from(Item.class);
Root<Item> item = query.from(Item.class);
Predicate predicate = assemblePredicateBasedOnParameters(parameterMap, item);
query.where(predicate);
//query.select(item);
TypedQuery<Item> q = entityManager.createQuery(query);
List<Item> result = q.getResultList();
System.out.println("results of query: "+result);
return result;
}
When I run it like above (with the query.select commented out), I get the following error: java.lang.IllegalStateException: No explicit selection and an implicit one cold not be determined at org.hibernate.jpa.criteria.CriteriaQueryImpl.validate(CriteriaQueryImpl.java:279)
当我像上面那样运行它(使用query.select注释掉)时,出现以下错误:
java.lang.IllegalStateException: No explicit selection and an implicit one cold not be determined at org.hibernate.jpa.criteria.CriteriaQueryImpl.validate(CriteriaQueryImpl.java:279)
That's odd, because it worked without a select back when the whole thing was in one method. 这很奇怪,因为当整个事情都用一种方法进行时,它没有选择地工作。
But if I actually call query.select(item);
但是,如果我实际调用
query.select(item);
, I get each Item as many times as the number of Items. ,我获得每个项目的次数是项目数量的两倍。 (I mean, there should be eight Items in total, now I get each of them eight times, so there are 64 records in total)
(我的意思是,总共应该有八个项目,现在我每个项目都有八次,因此总共有64条记录)
What is the cause of this behavior, and how should I fix it? 这种现象的原因是什么,我该如何解决?
It's kind of embarassing: there was an additional query.from(Item.class);
有点尴尬:还有一个额外的
query.from(Item.class);
by mistake. 因为失误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.