Joda time DateTime 错误地存储在数据库中
Posted
技术标签:
【中文标题】Joda time DateTime 错误地存储在数据库中【英文标题】:Joda time DateTime incorrectly stores in database 【发布时间】: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?
【问题讨论】:
【参考方案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
持久化DateTime
和java.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
文件中。
【讨论】:
以上是关于Joda time DateTime 错误地存储在数据库中的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jackson 进行 DateTime 反序列化的默认时区(Joda-Time 模块)
我如何判断一个 joda-time DateTime 对象是不是在另一个对象的 4 小时内?
这是joda time中的错误吗?处理非常古老(0000 年)的即时/负纪元
MySQL DATETIME 精度(joda-time、Hibernate、org.jadira.usertype、hbm2ddl)