在JPA中:使用CriteriaQuery计算where子句的查询结果

时间:2015-01-14 10:36:07

标签: java hibernate jpa criteriaquery

我是JPA及其CriteriaBuilder / CriteriaQuery API的新手:

我想查询一组对象的摘录(如下所示,我只选择结果的元素n到m)

查询本身运作良好,我得到了我期望的结果。

但如果我尝试计算可能结果的全部数量,我会得到一个java.lang.IllegalArgumentException:

  

org.hibernate.hql.internal.ast.QuerySyntaxException:路径无效:' generatedAlias1.prop1' [从com.myCompany.blablub.MyClass中选择count(generatedAlias0)作为generatedAlias0,其中(1 = 1)和(generatedAlias1.prop1 =:param0)]"

final CriteriaQuery<MyClass> criteriaQuery = builder.createQuery(MyClass.class);
    CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
    countQuery.select(builder.count(countQuery.from(MyClass.class)));

    Long totalCount = -1L;
    List<MyClass> MyClassList;

    Root<MyClass> root = criteriaQuery.from(MyClass.class);



    if(myClassFilter != null) {         

            List<Predicate> predicates = new ArrayList<Predicate>();

            if(myClassFilter.getProp1() != null) {
                Join<MyClass, MyOtherClass> myJoin1 = root.join(MyClass_.prop1);
                predicates.add(builder.equal(myJoin1.get(MyOtherClass_.blah), myClassFilter.getProp1() ));
            }

            if(myClassFilter.getProp2() != null) {
                predicates.add(builder.equal(root.get(MyClass_.blubb), myClassFilter.getProp2() ));
            }

            if(myClassFilter.getProp3() != null) {
                Join<MyClass, MyOtherClass> myJoin2 = root.join(MyClass_.foo);
                predicates.add(builder.equal(myJoin2.get(MyOtherClass_.bar), myClassFilter.getProp3() ));
            }


            if (myClassFilter.getSpecialPropList() != null) { 
                if (myClassFilter.getSpecialPropList().length>0) {
                        Predicate orPredicates = builder.disjunction();
                        for (String specialProp : myClassFilter.getSpecialPropList()) {
                            Join<MyClass, specialProp> specialPropJoin = root.join(MyClass_.specialProps);
                            Predicate newPredicate = builder.equal(specialPropJoin.get(specialProp_.dudum), specialProp);
                            orPredicates = builder.or(orPredicates, newPredicate);
                        }
                        predicates.add(orPredicates);
                }
            }

            Predicate finalPredicate = builder.conjunction();

            for(Predicate p: predicates) {
                finalPredicate = builder.and(finalPredicate, p);
            }

            criteriaQuery.select(root).where(finalPredicate);
            countQuery.where(finalPredicate);
    }

    count = entityManager.createQuery(countQuery).getFirstResult();

    TypedQuery<MyClass> typedQuery = entityManager.createQuery(criteriaQuery);

    if(first >= 0) {
        typedQuery.setFirstResult(first);
    }
    if(count > 0) {
        typedQuery.setMaxResults(count);
    }

    MyClassList = typedQuery.getResultList();

我希望你能给我一些关于我做错的提示。

我想我知道我的问题所在。

当我使用联接时,行为才会显示。

没有连接的查询如下所示:

select count(generatedAlias0) from MyClass as generatedAlias0 where ( 1=1 ) and ( generatedAlias0.blubb=:param0 )

但是当我想使用连接时,它看起来像这样:

select count(generatedAlias0) from MyClass as generatedAlias0 where ( 1=1 ) and ( generatedAlias1.blah=:param0 )

而没有计数的查询如下所示:

select generatedAlias0 from MyClass as generatedAlias0 inner join generatedAlias0.prop1 as generatedAlias1 where ( 1=1 ) and ( generatedAlias1.blah=:param0 )

它显然不知道generateAlias1是什么,因为缺少整个连接。 有谁知道我怎么能解决这个问题?

1 个答案:

答案 0 :(得分:0)

使用criteriaQUery的根创建连接。 您还需要使用countQuery的根创建连接。

Root<MyClass> countRoot = countQuery.from(MyClass.class);
Join<MyClass, MyOtherClass> mycountJoin = countRoot.join(MyClass_.foo);