【问题标题】:Hibernate Criteria API produces invalid SQL with aggregates when using orderBy()使用 orderBy() 时,Hibernate Criteria API 产生无效的 SQL 聚合
【发布时间】:2019-03-04 15:46:11
【问题描述】:

我在一个项目中使用 JPA,该项目使用 Spring Data 和 Hibernate 的 Criteria API。使用JpaSpecificationExecutor,我能够创建查询,让我可以使用Specification 在我的存储库中同时使用过滤和分页,只需调用Page<EventPost> findAll(Specification<EventPost> specification, Pageable pageable); 即可。

我现在遇到的问题是,如果不使用休眠生成这样的无效查询,我就无法对结果进行排序:

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

显然,Hibernate 必须在发出真正的 finder 查询之前计算行数,并错误地将我的 Criteria 中的 order by 子句添加到 select count(*) 语句中。

这是我在日志中看到的逐字记录:

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

这就是我创建查询的方式

@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()]));
}

当我删除 query.orderBy(cb.desc(root.get("createDate"))); 时,一切正常。任何想法这里可能有什么问题?

版本如下:

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

【问题讨论】:

  • 您返回一列一行count - 您希望如何订购?
  • 我自己并不真正需要行数。我假设计数是由于内部原因由休眠本身生成的,不是吗?我希望所有谓词的结果都按 createDate 排序。
  • 是否在此方法之外设置了某些内容?
  • @keyboardsamurai 你的假设很可能是错误的。
  • 您不应该按照您的规格订购。您正在调用一个包含Pagable 的方法,该对象还包含订购信息。您应该使用该对象传递排序,而不是自己做。

标签: java spring postgresql hibernate jpa


【解决方案1】:
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. 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 2012-07-04
    • 2011-08-31
    相关资源
    最近更新 更多