java标准API和JPA2 GroupBy发行日期
我正在编写一个查询,以从实体表中查找特定日期的日期及其计数,并遇到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)
请让我知道我做错了什么。相应的PostgresSQL查询应该可以解决这个问题,因为我可以对它进行测试,看看它是否可以工作
# 1 楼答案
这是一个老问题,但这个问题仍然相关。我试过你的解决办法,但对我无效。起作用的是
trunc
函数,而不是to_char
:看起来criteriabuilder不喜欢
groupBy
中的literal
# 2 楼答案
CriteriaApi提供了一个让我头疼的好方法,但不久前我确实找到了解决方案,为未来好奇的人们提供了答案:
您会注意到,我将在multi-select语句中投射列,并将groupBy转换为java。sql。日期类型。CriteriaApi具有严格的类型安全格式,因此,如果要聚合特定列,则不能混合groupBy和select语句的类型。我的问题是,我正在使用函数调用选择日期列,并试图将其应用于groupBy
虽然生成的查询语句通过命令行工作,但它不适用于CriteriaApi。它无法生成ResultSet的原因是,它假设groupBy中的投影和聚合不是同一类型(我认为),因此,如果需要在select语句中的某列上使用函数,并在该列上进行聚合,则需要考虑避免使用该函数的方法(我就是这么做的),或者使用您拥有的Hibernate EntityManager对象生成本机查询
这是不幸的,但我相信CriteriaApi有很多限制,这是其中之一。它可能应该作为一个bug提交给他们的团队,但我不确定在哪里可以这样做