【问题标题】:Joda time DateTime incorrectly stores in databaseJoda time DateTime 错误地存储在数据库中
【发布时间】:2012-04-21 22:54:31
【问题描述】:

我使用 org.jadira.usertype:usertype.jodatime:1.9 将 JodaTime DateTime 字段存储到 timestamptz 列。应用服务器有 +4 时区。数据库服务器 +9 时区。 new DateTime() 导致${currentTime+1hour}+9 其中+9 是时区(正确的值是${currentTime+5hours)+9)。

我还没有找到任何相关的主题。 java.util.Date 正确存储。

域对象具有以下映射属性:

static mapping = {
    dateCreated sqlType:'timestamptz'
}

如何正确存储 DateTime?

【问题讨论】:

    标签: hibernate grails groovy grails-orm jodatime


    【解决方案1】:

    只需设置 JPA 属性:

    <property name="jadira.usertype.autoRegisterUserTypes"
              value="true"/>
    <property name="jadira.usertype.databaseZone"
              value="jvm"/>
    <property name="jadira.usertype.javaZone"
              value="jvm"/>
    

    【讨论】:

    • 这个放在什么文件里?
    • @dgrant 在您的 persistence.xml 文件中
    • 有没有办法在没有 XML 文件的情况下做到这一点?到目前为止,我的项目正在使用纯注释进行配置...
    【解决方案2】:

    我有同样的问题。在配置中指定 app 和 db 区域解决了这个问题。

                <prop key="jadira.usertype.autoRegisterUserTypes">true</prop>
                <prop key="jadira.usertype.databaseZone">America/Los_Angeles</prop>
                <prop key="jadira.usertype.javaZone">America/Los_Angeles</prop>
    

    【讨论】:

    • 这个放在什么文件里?
    【解决方案3】:

    好的。我花了8个小时来解决这个问题。如果您使用usertype 项目来持久化JodaTime,则必须将PersistentDateTime 类的databaseZone 属性设置为等于当前应用程序服务器时区(不是数据库!)。

    但最好使用official hibernate support。它解决了开箱即用的问题,因为它使用java.utl.Date 持久化DateTimejava.util.Date 默认正确持久化

    【讨论】:

    • 官方的hibernate支持没有扩展到Hibernate 4.0。 :-( 你需要使用用户类型。
    【解决方案4】:

    尝试使用 -Duser.timezone=UTC 启动 JVM 到 JAVA_OPTS,这样时间就在一个区域中,然后您可以对其进行操作以将其转换为您所在的位置。

    【讨论】:

    • 这是一个很好的方法 - 但请注意,如果您已经将日期存储在数据库中的另一个时区,则不能这样做。换句话说,对于新项目没有问题,但对于那些有现有数据的项目要非常非常谨慎。
    【解决方案5】:

    费多尔,

    我是否正确假设您使用的是 Oracle TIMESTAMP WITH TIME ZONE 列?由于数据库之间对 JDBC 的处理方式不同,用户类型还不支持这种类型(即使用 TIME ZONE),尽管该项目很乐意接受补丁。

    这里有一些关于 Oracle 的很好的讨论:http://puretech.paawak.com/2010/11/02/how-to-handle-oracle-timestamp-with-timezone-from-java/

    【讨论】:

    • 我们使用的是 PostgreSQL timestamptz
    【解决方案6】:

    我通过创建其他 PersistentDateTime extends AbstractVersionableUserType 解决了这个问题。

    import java.sql.Timestamp;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.usertype.ParameterizedType;
    import org.jadira.usertype.dateandtime.joda.columnmapper.TimestampColumnDateTimeMapper;
    import org.jadira.usertype.spi.shared.AbstractVersionableUserType;
    import org.jadira.usertype.spi.shared.IntegratorConfiguredType;
    import org.joda.time.DateTime;
    
    public class PersistentDateTime extends AbstractVersionableUserType<DateTime, Timestamp, TimestampColumnDateTimeMapper> implements ParameterizedType, IntegratorConfiguredType {
    
    @Override
    public int compare(Object o1, Object o2) {
        return ((DateTime) o1).compareTo((DateTime) o2);
    }
    
    @Override
    public void applyConfiguration(SessionFactory sessionFactory) {
    
        super.applyConfiguration(sessionFactory);
    
        TimestampColumnDateTimeMapper columnMapper = (TimestampColumnDateTimeMapper) getColumnMapper();
        columnMapper.setDatabaseZone(null);
        columnMapper.setJavaZone(null);
    }
    }
    

    【讨论】:

      【解决方案7】:

      只是针对 Spring Boot 用户的更新。我能够做到以下几点:

      spring.jpa.properties.jadira.usertype:
        autoRegisterUserTypes: true
        databaseZone: jvm
        javaZone: jvm
      

      我把它放在我的application.yaml 文件中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-10
        • 2012-01-24
        • 2013-05-03
        • 2011-05-23
        • 2017-06-04
        • 2015-05-22
        • 1970-01-01
        相关资源
        最近更新 更多