- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
数据库函数 date_trunc('day', (entity.date AT TIME ZONE 'UTC'))
的 JPQL/JPA/Hibernate 等价物是什么?
我需要在 Spring Boot 应用程序中四舍五入到全天(和周等),Hibernate 运行在 Postgresql 数据库之上。这个查询在 native postgresql 中是可能的,但我还没有想出如何在 Hibernate 中进行。时区(如“UTC”、“欧洲/阿姆斯特丹”)和日期部分(如“日”、“年”)可能会有所不同,因此我不能将其设置为默认值。
我在 Hibernate 论坛上发现了一个没有任何回复的旧帖子:https://forum.hibernate.org/viewtopic.php?f=1&t=990451
我还发现了一个相关的 StackOverflow 问题,发帖人直接想选择某个日期作为某个时区。虽然它没有回复:HQL equivalent of Postgres' "datetime at time zone"
我的整个查询(没有 where)看起来像这样,所以用不同的方法来实现也可以。
"SELECT NEW " + AggregateQueryEntity.class.getName() +
"(date_trunc('" + aggregationPeriod.toString() +
"', a.date), a.alertConfiguration.id.id, a.alertConfiguration.name, a.alertLevel, count(*)) from Alert a" +
whereClause.toString() +
" GROUP BY 1, a.alertConfiguration.id.id, a.alertConfiguration.name, a.alertLevel" + //column 1 is the truncated date
" ORDER BY 1, alertLevel DESC"
Edit: comments on answer.
Vlad 的回答很好,我对其进行了一些调整,将日期部分也作为变量。此外,我必须重写标准的 Hibernate 行为,该行为将 Date
列生成为 timestamp without timezone
并明确地使它们 timestamp with timezone
通过把它放在我列定义:
@Column(columnDefinition = "TIMESTAMP WITH TIME ZONE") private Date date;
如需进一步阅读,请参阅 https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_timestamp_.28without_time_zone.29
根据 Vlad 的其他博文 https://vladmihalcea.com/how-to-store-date-time-and-timestamps-in-utc-time-zone-with-jdbc-and-hibernate/,使用 Hibernate 属性 hibernate.jdbc.time_zone
也是一个好主意。并以 UTC 启动 JVM。为了解决我所有的时区问题,我也必须这样做。
最佳答案
如 Hibernate User Guide 中所述, 你可以使用 EXTRACT
函数:
List<Integer> days = entityManager
.createQuery(
"select extract( day from c.timestamp ) " +
"from Call c ", Integer.class )
.getResultList();
或 day
函数:
List<Integer> days = entityManager
.createQuery(
"select day( c.timestamp ) " +
"from Call c ", Integer.class )
.getResultList();
MetadataBuilderContributor
注册 DATE_TRUNC 函数如果你还需要使用AT TIMEZONE
,你需要像这样注册PostgreSQL函数:
public class SqlFunctionsMetadataBuilderContributor
implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction(
"date_trunc",
new SQLFunctionTemplate(
StandardBasicTypes.TIMESTAMP,
"date_trunc('day', (?1 AT TIME ZONE 'UTC'))"
)
);
}
}
MetadataBuilderContributor
现在,您需要通过 hibernate.metadata_builder_contributor
配置属性向 Hibernate 提供 SqlFunctionsMetadataBuilderContributor
:
<property>
name="hibernate.metadata_builder_contributor"
value="com.vladmihalcea.book.hpjp.hibernate.query.function.SqlFunctionsMetadataBuilderContributor"
</property>
MetadataBuilderContributor
如果您使用的是 Spring Boot,则需要将以下配置添加到 application.properties
文件中:
spring.jpa.properties.hibernate.metadata_builder_contributor=com.vladmihalcea.book.hpjp.hibernate.query.function.SqlFunctionsMetadataBuilderContributor
然后,假设您在数据库中有以下 Post
实体:
Post post = new Post();
post.setId(1L);
post.setTitle(
"High-Performance Java Persistence"
);
post.setCreatedOn(
Timestamp.valueOf(
LocalDateTime.of(2018, 11, 23, 11, 22, 33)
)
);
entityManager.persist(post);
您可以像这样在 JPQL 中调用 date_trunc
函数:
Tuple tuple = entityManager
.createQuery(
"select p.title as title, date_trunc(p.createdOn) as creation_date " +
"from Post p " +
"where p.id = :postId", Tuple.class)
.setParameter("postId", 1L)
.getSingleResult();
assertEquals(
"High-Performance Java Persistence",
tuple.get("title")
);
assertEquals(
Timestamp.valueOf(
LocalDateTime.of(2018, 11, 23, 0, 0, 0)
),
tuple.get("creation_date")
);
如果要自定义时区,只需像这样将时区作为参数传递:
public static class SqlFunctionsMetadataBuilderContributor
implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction(
"date_trunc",
new SQLFunctionTemplate(
StandardBasicTypes.TIMESTAMP,
"date_trunc('day', (?1 AT TIME ZONE ?2))"
)
);
}
}
现在,您可以按如下方式调用date_trunc
函数:
Tuple tuple = entityManager
.createQuery(
"select p.title as title, date_trunc(p.createdOn, :timezone) as creation_date " +
"from Post p " +
"where p.id = :postId", Tuple.class)
.setParameter("postId", 1L)
.setParameter("timezone", "UTC")
.getSingleResult();
我在我的 high-performance-java-persistence GitHub 存储库中创建了以下测试用例,它们运行得很好:
关于java - 使用 JPA 和 Hibernate 时,PostgreSQL date_trunc ('day' , (entity.date AT TIME ZONE 'UTC' )) 函数的 JPQL 等价物是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53499478/
在类中实现 NSCopying 的此方法以启用复制时,区域参数使用什么?如果我设置一个新对象,我不需要用 allocWithZone 来分配它,因为 alloc 就足够了......我很困惑.....
本文整理了Java中io.sphere.sdk.zones.Zone.getLocations()方法的一些代码示例,展示了Zone.getLocations()的具体用法。这些代码示例主要来源于Gi
本文整理了Java中io.sphere.sdk.zones.Zone.getId()方法的一些代码示例,展示了Zone.getId()的具体用法。这些代码示例主要来源于Github/Stackover
本文整理了Java中io.sphere.sdk.zones.Zone.referenceTypeId()方法的一些代码示例,展示了Zone.referenceTypeId()的具体用法。这些代码示例主
本文整理了Java中io.kaif.model.zone.Zone.valueOf()方法的一些代码示例,展示了Zone.valueOf()的具体用法。这些代码示例主要来源于Github/Stacko
本文整理了Java中io.kaif.model.zone.Zone.tryFallback()方法的一些代码示例,展示了Zone.tryFallback()的具体用法。这些代码示例主要来源于Githu
我的数据库中恰好有包含 timestamp without time zone 列的表。现在我需要根据时区比较它们。 我可以这样做: select my_timestamp::timestamp wi
我正在尝试 Angular 2。但是在将 zone.js 作为全局变量导入后出现此错误: 我的包及其版本: "dependencies": { "angular2": "2.0.0-beta.
可能我问这个问题已经太晚了,但无论如何。 有人可以解释一下在什么情况下我需要导入区域的补丁 - zone.js/dist/zone-patch-rxjs。据我所知,补丁已添加到此 PR 中(this
问题很简短:如果我已经在没有时区的时间戳类型的列中有数据,如果我将类型设置为带时区的时间戳,postgresql 将如何处理这些数据? 最佳答案 它将当前值保留在本地时间并将时区设置为本地时间的偏移量
我有一个在东部时区的时间,但我想将它调整为中部时区。两个时区都在美国。我从来没有这样做过?我不知道如何转换它。请帮帮我好吗? 最佳答案 这是一种可能的方法: $dt = new DateTime('2
我在 Angular 11 上有一个应用程序刚刚开始在所有浏览器、所有环境(本地/暂存/生产)上同时出现错误(大约一个小时前,没有任何更新或任何东西): Uncaught TypeError: t.g
我们有一个函数,可以像 JS 一样解析 UTC 中的日期/时间对,但随后强制它的行为就像在本地时区中指定的一样。如下: var tz = (new Date()).toString().match(/
我很难理解 "AT TIME ZONE 'localtime'" 究竟是如何工作的?通过使用它,我发现它的行为与 "AT TIME ZONE 'UTC'" 完全一样......但是为什么呢? "loc
我在 PostgreSQL 9.3 ALTER TABLE manual page 中找到了这个 ALTER COLUMN 语句: ALTER TABLE audits ALTER COLUM
首先,我意识到不推荐使用 time with time zone。我要使用它是因为我将多个 time with time zone 值与我当前的系统时间进行比较,而不管是哪一天。 IE。用户说每天 0
在 Rails 控制台中: > ActiveSupport::TimeZone['Samoa'].utc_offset => -39600 > ActiveSupport::TimeZone['Sam
我在两个不同的数据库中运行了相同的语句:我的本地数据库和 Oracle Live SQL . CREATE TABLE test( timestamp TIMESTAMP DEFAULT SY
我在两个不同的数据库中运行了相同的语句:我的本地数据库和 Oracle Live SQL . CREATE TABLE test( timestamp TIMESTAMP DEFAULT SY
在 Rails 3.0.10 中,我使用 Time.zone 来更改用户查看美国各地发布的类(class)时间的方式。然而,更改时区似乎并不像我期望的那样 Time.zone = TZInfo::Ti
我是一名优秀的程序员,十分优秀!