我正在编写一个查询,以便从我的实体表中查找该特定日期的日期及其计数,并遇到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看到这样做会导致错误
&#34; org.hibernate.exception.SQLGrammarException:无法解压缩 结果集&#34;
还有从我的调试器中找到的构建查询字符串:
select function('TO_CHAR', generatedAlias0.date, :param0), count(generatedAlias0) from LogMessageEntity as generatedAlias0 group by function('TO_CHAR', generatedAlias0.date, :param1)
请让我知道我做错了什么。相应的Postgres SQL查询应该适用于此,因为我可以测试它并看到它可以工作。
答案 0 :(得分: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有很多限制,其中就是其中之一。它可能应该作为一个错误提交给他们的团队,但我不知道该在哪里做。
答案 1 :(得分: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);
看起来标准制作者不喜欢literal
中的groupBy
。