我正在使用 ZonedDateTime 来跟踪系统中发生的事件。例如
class PurchaseOrder {
// The rest is skipped
@Column(name = "created", columnDefinition = "TIMESTAMP WITH TIME ZONE", nullable = false)
private ZonedDateTime created;
}
为了运行一些测试,我在内存数据库中使用了 hsqldb。我通过在配置 .properties 文件中指定它来运行 sql 脚本来填充它
spring.jpa.properties.hibernate.hbm2ddl.import_files=create-for-test.sql
在该文件中,我插入一条记录为
INSERT INTO purchase_order (id, consumer_id, provider_id, created, modified, purchase_order_status_id)
VALUES
(1, 1001, 1, '2017-01-11 11:45:20.523+01:00', NULL , 1);
它执行没有任何问题。
后来,当我从运行@NamedQuery 的数据库中获取这条记录时,我总是得到一个本地时区的值。发生读取的日志部分是:
Hibernate: select purchaseor0_.id as id1_52_, purchaseor0_.consumer_id as consumer5_52_, purchaseor0_.created as created2_52_,... from purchase_order purchaseor0_ where purchaseor0_.id=?
binding parameter [1] as [BIGINT] - [1]
extracted value ([id1_52_] : [BIGINT]) - [1]
extracted value ([consumer5_52_] : [BIGINT]) - [1001]
extracted value ([created2_52_] : [TIMESTAMP]) - [2017-01-11T11:45:20.523-08:00[America/Los_Angeles]]
所以:我用 TimeZone +01:00 插入它,Hibernate 堆栈在本地 TimeZone -08:00 中读回它。
有没有办法用正确的区域实际读取整个时间戳?
相同的代码在 Postgres 的生产环境中运行,并且时间戳在那里按预期运行(即我可以编写和读取 ZonedDateTime 并且区域信息不会丢失)。
编辑:@fredt Postgress 也返回 Timestamp,但“尊重”脚本中指定的时区。
例子:
UPDATE product
SET
published_from = '2017-01-01 00:00:00.000+01:00',
published_to = '2017-01-31 00:00:00.000+01:00'
WHERE id = 3312;
和日志输出:
select distinct productimp0_.id as id1_39_, ...
productimp0_.published_from as publish16_39_, productimp0_.published_to as publish17_39_, ...
from product productimp0_ where productimp0_.id=?
binding parameter [1] as [BIGINT] - [3312]
...
extracted value ([publish16_39_] : [TIMESTAMP]) - [2016-12-31T15:00-08:00[America/Los_Angeles]]
extracted value ([publish17_39_] : [TIMESTAMP]) - [2017-01-30T15:00-08:00[America/Los_Angeles]]
在 INSERT 语句中使用了 UTC+01(欧洲时间),休眠/驱动程序将其转换为本地时间(UTC-08)。只要我得到正确的时间点,这对我来说很好,因为在内部,完整的应用程序知道时区等。