在Spring Data JPA中,JDBC(在Spring Data JPA中)在向Oracle DB中插入一条记录时,并不总是采用JVM的默认时区吗?

问题描述 投票:0回答:1

在我的应用程序开始时,我已经使用 "Spring Data JPA "将默认时区设置为AustraliaPerth。Timezone.setDefaultTimezone() 方法。我正试图在 created_date 栏目。当 save 在调用Spring data JPA的方法时,时间戳是澳大利亚时区下午4点。但是,在DB中,它被存储为下午4点的UTC。我们的Spring配置没有强制JDBC使用UTC时区。没有指定这样的配置。事实上,在版本库中根本就没有UTC。

问题:我知道JDBC驱动决定了时区。问题:我知道JDBC驱动是决定时区的,那么它是不是应该总是使用JVM默认的时区,在这种情况下是澳大利亚?问:无论我在代码中设置什么时区(无论是作为默认时区还是在日期列中),在DB中总是UTC。但是时间戳的数字部分是正确的。Q) JDBC使用的是哪个时区--JVM的默认时区还是DB的 "DBtimezone"(在本例中,恰好是后者)?或者可以是任何时区?

信息:DB的Dbtimezone - select dbtimezone from dual - UTCSessiontimezone of DB - AsiaCalcuttaCreated_date列的类型是'TIMESTAMP WITH TIMEZONE'。

注:我试过用java.time类。OffsetdateTime和ZonedDateTime,但是没有成功。

java spring hibernate jdbc timezone
1个回答
1
投票

永远不要设置默认时区。这样做会立即影响在该JVM内运行的所有应用程序的所有线程中运行的所有其他代码。而任何其他代码都可以再次重置它。

所以永远不要编写依赖于JVM当前默认时区的代码。明确地指定你想要的预期时区。

我试图在created_date列中插入一个澳大利亚时区的时间戳。

(A) 请确定你的数据库列的类型类似于SQL标准的类型 TIMESTAMP WITH TIME ZONE.

(B) 只使用现代 java.time 类型。

(C) 使用符合JDBC 4.2及以上的JDBC驱动程序。

我不使用JPA。但我可以直接给你看JDBC。

ZoneId z = ZoneId.of( "Australia/Perth" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;

你可能会被一些工具和中间件所迷惑,这些工具和中间件有一个不幸的反功能,那就是在从数据库中获取值后,但在显示给你之前,动态地应用一个默认时区。这就造成了一个并不存在的时区的假象。试着用Java从数据库中检索你的值。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

用这个答案上的代码就不会出现时区问题了 根据我的经验 JDBC驱动程序 对于 PostgresH2在服务器或客户端上,没有与任何默认时区的交互。坚持(a)使用java.time类,(b)总是指定你所期望的预期时区,而不是隐含地依赖一个默认时区。我没有使用Spring或Hibernate,所以我不知道它们是否可能在途中注入一个时区。

试着用一些直接的JDBC来消除Spring和JPAHibernate的影响,同时调试一下你的情况。


对了,时区 Asia/Calcutta 已改名为 Asia/Kolkata. 确保 tz数据 在您的操作系统、数据库引擎和Java实现中,所有这些都是最新的。

© www.soinside.com 2019 - 2024. All rights reserved.