目标是根据客户的UTC时间(按客户的UTC时间添加客户端的时区偏移量)将按GMT 0时间戳(按月/日/小时)存储的数据分组。
在SQL中,查询应该类似于(按天分组):
SELECT *
FROM myentity
GROUP BY dayofweek ( date_add (mytimestampcolumn, INTERVAL timezonedifference hours ))
在JPA中,以下代码工作正常,因为“dayofweek”是jpa的已知(注册)函数:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
Expression<Integer> timeUnitFunction = criteriaBuilder.function("dayofweek", Integer.class, from.<Date>get("timestampColumn"));
query.groupBy(timeUnitFunction);
然而,它不考虑时区偏移,所以我想使用另一个db函数并将第二行更改为:
criteriaBuilder.function("dayofweek", Integer.class, criteriaBuilder.function("date_add", Date.class, "hour", timezoneDifferece, from.<Date>get("timestampColumn")))
从我看到的情况来看,只有ADD_DATE
和ADD_TIME
注册了JPA函数。
使用自定义方言来计算简单的时区偏移似乎有点矫枉过正。
有关替代JPA注册函数的任何建议,可以操纵时间戳或任何其他方式获得想要的结果(按月/天/小时在不同的时区偏移上正确分组)将非常感激。
修改
正如Neil评论的那样,date_add和任何其他SQL函数都可以通过CriteriaBuilder
的函数方法调用。
但是,我无法提供date_add所需的“INTERVAL expr unit”格式参数(使用CriteriaBuilder.literal
创建字符串表达式不起作用)。
问题已解决使用带有字符串文字的SQL“convert_tz”函数作为时区值。
答案 0 :(得分:1)
您可以使用cb.function(sqlFuncName, args)
方法来调用任何SQL函数。 args 是表达式,传入的函数与SQL函数一样多。如果这些 args 是文字,那么您可以使用cb.literal(value)
将其转换为表达式。
也许使用这些组件,您可以生成符合您目的的内容。请注意,通过调用SQL函数,您可能会失去RDBMS可移植性,但这可能不是您的情况所关注的。