简体   繁体   中英

Hibernate Criteria API produces invalid SQL with aggregates when using orderBy()

I am using JPA in a project that uses Spring Data with Hibernate's Criteria API underneath. Using JpaSpecificationExecutor I was able to create queries that would let me use filtering and paging at the same time in my repository using a Specification , by just calling Page<EventPost> findAll(Specification<EventPost> specification, Pageable pageable); without a hitch.

The Problem that I have now, is that I can't order the results without hibernate generating invalid queries like this one:

select count(eventpost0_.event_id) as col_0_0_ from event_post eventpost0_ where eventpost0_.category_event_category_id=? order by eventpost0_.createDate desc

Apparently, Hibernate has to count the rows before it issues the real finder query, and erroneously adds the order by clause from my Criteria to the select count(*) statement.

This is verbatim what I see in the logs:

2016-09-05 09:22:36.987 [http-bio-8080-exec-4] DEBUG org.hibernate.SQL - select count(eventpost0_.event_id) as col_0_0_ from event_post eventpost0_ where eventpost0_.category_event_category_id=? order by eventpost0_.createDate desc
2016-09-05 09:22:36.991 [http-bio-8080-exec-4] WARN  o.h.e.j.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42803
2016-09-05 09:22:36.992 [http-bio-8080-exec-4] ERROR o.h.e.j.spi.SqlExceptionHelper - ERROR: column "eventpost0_.createdate" must appear in the GROUP BY clause or be used in an aggregate function
  Position: 133

And this is how I create my query

@Override
public Predicate toPredicate(Root<EventPost> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path<EventPost> category = root.get("category");
        Path<Long> participants = root.get("participants");
        Path<EventPostType> eventPostType = root.get("eventPostType");

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

        if(criteria.getEventCategory()!=null){
            predicates.add(cb.equal(category,criteria.getEventCategory()));
        }

        if(criteria.getParticipantsFrom()!=null){
            predicates.add(cb.ge(participants,criteria.getParticipantsFrom()));
        }else if(criteria.getParticipantsTo()!=null){
            predicates.add(cb.lt(participants,criteria.getParticipantsTo()));
        }

        if(criteria.getEventPostType()!=null){
            predicates.add(cb.equal(eventPostType,criteria.getEventPostType()));
        }

        query.orderBy(cb.desc(root.get("createDate")));

        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}

When I remove query.orderBy(cb.desc(root.get("createDate"))); , everything works fine. Any Ideas what might be wrong here?

Versions are as follows:

PostgreSQL Database 9.5.3.0 with PostGIS
spring-orm:jar:4.2.5.RELEASE
spring-data-jpa:jar:1.9.4.RELEASE
hibernate-spatial:jar:4.3:compile
hibernate-core:jar:4.3.11.Final:compile
postgresql:jar:8.4-701.jdbc4:compile
postgis-jdbc:jar:1.5.2:compile
I have the following code which worked for me 

CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<T> cq = cb.createQuery(entity);
    Root<T> root = cq.from(entity);

 cq.orderBy(cb.desc(cb.sum(root.get(orderByString))));

// orderByString is string entity field that is being aggregated and which we want to put in orderby clause as well. 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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