2015-08-28 163 views
1

我正在寫一個查詢來查找來自我的實體表的特定日期的日期和計數,並運行到groupBy語句的問題中。Criteria API和JPA2 GroupBy與日期問題

這裏是我的標準API調用:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 
    CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery(); 
    Root<HtEntity> from = criteriaQuery.from(entityClassType); 

    Expression<String> log_date = criteriaBuilder.function("TO_CHAR", 
      String.class, from.get(Constants.PARAM_DATE), criteriaBuilder.literal("yyyy-MM-dd") 
    ); 

    //create the select statement 
    criteriaQuery.select(
      criteriaBuilder.tuple(
        log_date.alias("log_date"), 
        criteriaBuilder.count(from))); 

    criteriaQuery.groupBy(log_date); //ISSUE HERE!!! 

    TypedQuery<Tuple> query = em.createQuery(criteriaQuery); 
    List<Tuple> results = query.getResultList(); 

,但不嘗試與TO_CHAR投日期列在僅使用日期列它的工作原理,但顯然不是聚合爲我想。我只想在YYYY-MM-DD,而不是整個時間戳的日期,我只能看到使用GROUPBY導致錯誤這樣

「org.hibernate.exception.SQLGrammarException:無法提取 結果集」

而且有查詢字符串,它是從我的調試發現編譯:

select function('TO_CHAR', generatedAlias0.date, :param0), count(generatedAlias0) from LogMessageEntity as generatedAlias0 group by function('TO_CHAR', generatedAlias0.date, :param1) 

請讓我知道我做錯了。相應的Postgres SQL查詢應該爲此工作,因爲我可以測試它並看到它會起作用。

+0

嘿,你有沒有找到解決辦法? – Ayushi

+0

是的,我會添加一個答案來顯示解決方案 – rosenthal

回答

0

CriteriaApi有給我提供了一個頭痛的一個很好的方式,但我並最終找到了一個解決這個一會兒回來,爲未來的好奇,人們的答案:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 
CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class); 
Root<MyEntity> from = criteriaQuery.from(classType); 

criteriaQuery.multiselect(
    from.get("date").as(java.sql.Date.class), 
    criteriaBuilder.count(from) 
); 

/*Add order by and group by clause*/ 
criteriaQuery.orderBy(criteriaBuilder.desc(from.get("date").as(java.sql.Date.class))); 
criteriaQuery.groupBy(from.get("date").as(java.sql.Date.class)); 

TypedQuery<Object[]> query = em.createQuery(criteriaQuery); 
List<Object[]> results = query.getResultList(); 

你會發現,我我在我的multi-select語句中強制投射列,而我的groupBy是java.sql.Date類型。 CriteriaApi具有嚴格的類型安全格式,因此如果您要彙總該特定列,則不能混合groupBy和select語句的類型。我的問題是我在日期列上選擇了一個函數調用,並試圖將它應用到groupBy。

雖然生成的查詢語句通過命令行工作,但它不適用於CriteriaApi。它無法生成ResultSet的原因是因爲它假設groupBy中的投影和聚合不是相同的類型(我認爲),因此,如果您需要在select語句的列中使用函數,並在列,你需要想辦法避免使用函數(這是我所做的),或者使用Hibernate EntityManager對象生成本機查詢。

這是不幸的,但我相信CriteriaApi有一些限制,這是其中之一。它可能應該作爲一個bug提交給他們的團隊,但我不確定在哪裏做這件事。

0

老問題,但問題仍然相關。我已經嘗試了您的解決方案,但它對我無效。做什麼工作是trunc功能,而不是to_char

Path<FeedbackType> feedbackTypePath = itemRoot.get("feedbackType"); 
    final Expression date = criteriaBuilder.function("trunc", java.sql.Date.class, votesJoin.get("creationDate")); 

    selects.add(feedbackTypePath); 
    selects.add(date); 
    selects.add(criteriaBuilder.count(itemRoot.get("id"))); 

    criteriaQuery.multiselect(selects); 
    criteriaQuery.where(criteriaBuilder.equal(votesJoin.get("creationDate"), oldestVoteSubquery)); 
    criteriaQuery.groupBy(feedbackTypePath, date); 

它看起來像criteriabuilder不喜歡在groupByliteral