Search code examples
sqlhibernatejpa-2.0criteria

How to Create a Criteria Query with AVG and GROUP using JPA


I wanted to get the list of products based on average customer rating using Criteria query. I wrote a piece of code using criteria query aggregate functions AVG and kept GROUP BY clause. But somehow i am getting "Not a Group BY Expression" exception. I tried and searched in Google in order to resolve the but nothing was helpful. Posting the code below

CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Object[]> cq = builder.createQuery(Object[].class);
        Root<GdbCustomerProductReviewImpl> productReview = cq.from(GdbCustomerProductReviewImpl.class);
        Path productPath = productReview.get("product");
        Path documentPath = productPath.get("photo");
        Path categoryPath = productPath.get("defaultCategory");
        Path productCategoryPath = categoryPath.get("prdCategory");
        cq.multiselect(productReview.get("id"),productPath.get("url"),productPath.get("skuName"),documentPath.get("id"));
        cq.where(builder.isNotNull(productPath.get("id")));
        cq.where(builder.equal(productReview.get("status"),"ACTIVE"));
        cq.where(builder.equal(productReview.get("reviewType"),"PRODUCT"));
        cq.where(builder.equal(productPath.get("isEnable"),Boolean.TRUE));
        cq.where(builder.equal(productPath.get("status"),StatusType.APPROVED.getType()));
        cq.where(builder.isNotNull(productPath.get("defSkuMap")));
        cq.where(builder.equal(productCategoryPath.get("isEnabled"),Boolean.TRUE));
        cq.groupBy(productReview.get("id"));
        Expression event_count = builder.avg(productReview.get("rating"));
        cq.orderBy(builder.desc(event_count));
        List<Object[]> resultList = em.createQuery(cq).setMaxResults(size).getResultList();

Solution

  • On further Research found out a solution and also thanks to crizzis. Posting the solution which had worked for me.

    CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<Object[]> cq = builder.createQuery(Object[].class);
            Root<GdbCustomerProductReviewImpl> productReview = cq.from(GdbCustomerProductReviewImpl.class);
            Path productPath = productReview.get("product");
            Path documentPath = productPath.get("photo");
            Path categoryPath = productPath.get("defaultCategory");
            Path productCategoryPath = categoryPath.get("prdCategory");
            Expression event_count = builder.avg(productReview.get("rating"));
            cq.multiselect(productPath.get("id"),productPath.get("url"),productPath.get("skuName"),documentPath.get("id"));
            cq.where(builder.isNotNull(productPath.get("id")),builder.equal(productReview.get("status"),"ACTIVE"),builder.equal(productReview.get("reviewType"),"PRODUCT"),builder.equal(productPath.get("isEnable"),Boolean.TRUE),builder.equal(productPath.get("status"),StatusType.APPROVED.getType()),builder.isNotNull(productPath.get("defSkuMap")),builder.equal(productCategoryPath.get("isEnabled"),Boolean.TRUE));
            cq.groupBy(productPath.get("id"),productPath.get("url"),productPath.get("skuName"),documentPath.get("id"));
           
            cq.orderBy(builder.desc(event_count));
            List<Object[]> resultList = em.createQuery(cq).setMaxResults(size).getResultList();