使用JPA中的SQL函数处理时间戳(GMT到给定的UTC)

时间:2015-04-06 11:06:38

标签: java mysql hibernate jpa

目标是根据客户的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_DATEADD_TIME注册了JPA函数。

使用自定义方言来计算简单的时区偏移似乎有点矫枉过正。

有关替代JPA注册函数的任何建议,可以操纵时间戳或任何其他方式获得想要的结果(按月/天/小时在不同的时区偏移上正确分组)将非常感激。

修改 正如Neil评论的那样,date_add和任何其他SQL函数都可以通过CriteriaBuilder的函数方法调用。

但是,我无法提供date_add所需的“INTERVAL expr unit”格式参数(使用CriteriaBuilder.literal创建字符串表达式不起作用)。

问题已解决使用带有字符串文字的SQL“convert_tz”函数作为时区值。

1 个答案:

答案 0 :(得分:1)

您可以使用cb.function(sqlFuncName, args)方法来调用任何SQL函数。 args 是表达式,传入的函数与SQL函数一样多。如果这些 args 是文字,那么您可以使用cb.literal(value)将其转换为表达式。

也许使用这些组件,您可以生成符合您目的的内容。请注意,通过调用SQL函数,您可能会失去RDBMS可移植性,但这可能不是您的情况所关注的。