【问题标题】:hibernate 5 + ZonedDateTime + postgresql include time zone and the offsethibernate 5 + ZonedDateTime + postgresql 包括时区和偏移量
【发布时间】:2016-03-04 16:43:54
【问题描述】:

我有一个正在运行的应用程序 spring boot 1.3 + hibernate 5 + java 8 + ZonedDateTime + postgresql 并且在其中一个表中我有以下字段。

@Column(name = "DATE_ENABLED")
@Type(type="java.time.ZonedDateTime")   
private ZonedDateTime dateEnabled;

@Column(name = "DATE_DISABLED")
@Type(type="java.time.ZonedDateTime")   
private ZonedDateTime dateDisabled;

如果我运行该应用程序,那么我会看到默认情况下会生成“没有时区的时间戳”

testDB=# \d type
                Table "public.type"
             Column             |            Type             | Modifiers 
--------------------------------+-----------------------------+-----------
 type_id                        | bytea                       | not null
 date_disabled                  | timestamp without time zone | 
 date_enabled                   | timestamp without time zone | 

我知道,如果我将 columnDefinition="TIMESTAMP WITH TIME ZONE" 添加到列中,即类似于

@Column(name = "DATE_DISABLED", columnDefinition= "TIMESTAMP WITH TIME ZONE")

然后它工作正常,我可以看到 hibernate 创建了一个带时区的列,但是如果我理解正确,这将只适用于 postgres,即如果我明天将数据库更改为 mysql,那么 hibernate 将抛出一个错误.

因此,我的问题是一般如何做到这一点,即告诉休眠创建一个应包含时区和偏移量的列。我的观点是,由于故意创建 java 类型“ZonedDateTime”以包括时区和 UTC 时间偏移,那么休眠将默认创建一个包含时区的列。因此问题又来了:告诉hibernate包含时区和偏移量的正确方法是什么。

这是我的 pom 的一部分:

    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.0.RELEASE</version>

    <hibernate.version>5.0.4.Final</hibernate.version>

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-java8</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

我的属性文件显示方言

    @Bean
    public  Properties hibernateProperties() {
      return new Properties() {
        {
            setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
            setProperty("hibernate.chach.provider_class", "org.hibernate.cache.NoCacheProvider");
            setProperty("hibernate.show_sql", "true");              
            setProperty("hibernate.hbm2ddl.auto", "create-drop");
         }
      };
   }

【问题讨论】:

  • 仅供参考,只是为了确认您的怀疑,是的,您是正确的,数据类型 timestamp without time zone 不适合存储 ZonedDateTime 的值。应该是 timestamp with time zone 类型的列来存储时刻,时间线上的特定点,如 ZonedDateTime 所示,Postgres 调整为 UTC 进行存储。缺少任何时区或与 UTC 偏移的概念,timestamp without time zone 无法存储片刻。列类型timestamp without time zone 映射到Java 类型LocalDateTime

标签: hibernate postgresql java-8 hibernate-5.x


【解决方案1】:

如果您使用 Hibernate 创建模式,这个问题似乎只是一个障碍。因此,如果在 PostgreSQL 上将列创建为 timestamp with time zone 后一切正常,那就继续吧。无论如何,让 Hibernate 生成您的模式是一种不好的做法。手动执行(或让 DBA 执行此操作)。如果您想自动化,请在可靠的人编写 sql 脚本后使用FlywayLiquibase 之类的数据库迁移工具。

除此之外,“明天改变数据库”的要求听起来真的很虚构,独立工作的数据库或多或少是不现实的,并且在编写必须执行的更大应用程序时变得更加困难。

如果您需要有关 Hibernate / JDBC 时间戳行为的更多信息,请查看this nice article about that

【讨论】:

    猜你喜欢
    • 2011-09-23
    • 2016-11-25
    • 2011-01-07
    • 2014-12-28
    • 1970-01-01
    • 2015-05-30
    • 2011-08-04
    • 2021-07-26
    • 1970-01-01
    相关资源
    最近更新 更多