java - Criteria API 和 JPA2 GroupBy 日期问题

标签 java hibernate postgresql jpa criteria

我正在编写查询以从我的实体表中查找日期及其对特定日期的计数,并遇到 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: could not extract ResultSet"

还有从我的调试器中找到的查询字符串:

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

请让我知道我做错了什么。相应的 Postgres SQL 查询应该适用于此,因为我可以对其进行测试并查看它是否可行。

最佳答案

CriteriaApi 有一个让我头疼的好方法,但我确实在不久前找到了解决这个问题的方法,为 future 好奇的人提供了答案:

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();

您会注意到我在多选语句中转换列,并将 groupBy 转换为 java.sql.Date 类型。 CriteriaApi 具有严格的类型安全格式,因此如果您在该特定列上进行聚合,则不能混合使用 groupBy 和 select 语句的类型。我的问题是我正在通过函数调用在日期列上进行选择,并且还试图将其应用于 groupBy。

虽然生成的查询语句可通过命令行运行,但不适用于 CriteriaApi。它无法生成 ResultSet 的原因是因为它假设 groupBy 中的投影和聚合不是同一类型(我认为),因此,如果您需要在 select 语句中的列上使用函数并在该列上进行聚合专栏中,您需要想出一种可以避免使用该函数的方法(我就是这样做的),或者使用您拥有的 Hibernate EntityManager 对象生成 native 查询。

这很不幸,但我相信 CriteriaApi 有很多限制,这就是其中之一。它可能应该作为错误提交给他们的团队,但我不确定在哪里做。

关于java - Criteria API 和 JPA2 GroupBy 日期问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32278039/

相关文章:

java - 如何使用 Hibernate 注释标记外键约束?

Postgresql:将 % 附加到数组元素的开头和结尾

java - 如果输入一个数字,同时将每个数字加上 n 次幂,对应于下面给出的公式,如何对数字进行求和?

java - 是否可以从另一个类访问非静态类的实例

mysql - 如何使用hibernate交换数据库中的id

c - 需要扩展库才能使用 PG_MODULE_MAGIC 宏

c - 如何对 PostgreSQL C 语言函数进行单元测试

java - 使用线程中断来唤醒线程?

java - OpenGL es 2.0 颜色

java - 如何使用 Spring、Hibernate、EntityManager 和 JPA 连接到 mysql 数据库