简体   繁体   English

JPA Criteria动态谓词创建

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM