在h2数据库中存储LocalDate实例的正确方法是什么?
我正在使用数据类型TIMESTAMP
,但根据user.timezone
java进程开始的奇怪行为。
当我插入TIMESTAMP
与时区美国/多伦多-并读取它与时区UTC -2021-05-01
将有1小时的差异,但2021-01-01
没有。
复制的步骤
确保当前文件夹中有h2-1.4.196.jar
。启动h2控制台:
java -Duser.timezone=America/Toronto -cp h2*.jar org.h2.tools.Console
对于我正在使用的JDBC URL,我认为不是所有的都是相关的,但MV_STORE=FALSE
和MVCC=FALSE
应该是重要的。
jdbc:h2:~/mydb;DATABASE_TO_UPPER=FALSE;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=60000;CACHE_SIZE=16384;AUTO_SERVER=TRUE;MV_STORE=FALSE;MVCC=FALSE
运行以下查询创建一个新表:
CREATE TABLE foo (
time TIMESTAMP NULL,
);
插入两行:
INSERT INTO foo VALUES (TIMESTAMP '2021-05-01 00:00:00.0')
INSERT INTO foo VALUES (TIMESTAMP '2021-01-01 00:00:00.0')
验证插入数据是否成功,返回:
SELECT * FROM foo;
time
2021-05-01 00:00:00.0
2021-01-01 00:00:00.0
现在停止您启动的java进程,这次使用以下命令运行它,注意user.timezone
是不同的:
java -Duser.timezone=UTC -cp h2*.jar org.h2.tools.Console
使用上面相同的URL连接并运行上面相同的SELECT查询。仅观察第一个条目的结果中的小时差。
SELECT * FROM foo;
time
2021-04-30 23:00:00.0
2021-01-01 00:00:00.0
2021年3月28日凌晨02:00在一些国家已被转发到凌晨03:00。这是世界上许多国家实行的多少有些人为的夏时制(顺便说一句,公平地说,这是现任土耳其总统的成就,土耳其[现在的
多伦多有夏令时。
H2忽略用户。我想是时区吧。但并非完全如此。根据xerx593的评论,我同意,这是一个bug。
取消夏令时:https://twitter.com/VitalikButerin?s=20& t = FiPQedQk0YY1ywzPPA6VlA
您使用的是完全过时且不受支持的H2数据库版本,甚至更多,您在其中使用了遗留存储后端,PageStore(不像MVStore)并不真正支持JVM时区的更改.
你需要使用默认的MVStore后端,你也应该考虑升级,在H2 1.4.196中对JSR-310 Java数据类型(java.time.*
)的支持存在各种已知问题。