Java 如何防止hibernate加载错误的日期?
问题是我从DAO的加载函数中得到了错误的日期 观察到的日期存储在PostgreSQL数据库中(来自用户表的birthdate列),等于1982-03-28。它有时被称为1982-03-27。我从更有经验的用户那里得到了一些提示,他们说这与时区问题有关 错误的值来自java.util.Date类的实例。我通过Calendar类的对象获取它们。当我叫这个小家伙:Java 如何防止hibernate加载错误的日期?,java,hibernate,postgresql,date,tapestry,Java,Hibernate,Postgresql,Date,Tapestry,问题是我从DAO的加载函数中得到了错误的日期 观察到的日期存储在PostgreSQL数据库中(来自用户表的birthdate列),等于1982-03-28。它有时被称为1982-03-27。我从更有经验的用户那里得到了一些提示,他们说这与时区问题有关 错误的值来自java.util.Date类的实例。我通过Calendar类的对象获取它们。当我叫这个小家伙: calendar.getTimeZone().getDisplayName() 它回来了 Central European Time
calendar.getTimeZone().getDisplayName()
它回来了
Central European Time
“生日”列的类型为:
无时区的生日时间戳
postgresql.conf文件中设置的时区变量的值等于波兰
load方法的内部实现如下所示:
public T load(ID aPrimaryKey, boolean aLock)
{
if (aPrimaryKey == null) {
throw new IllegalArgumentException("Parameter aPrimaryKey can't be null!");
}
preLoad(aPrimaryKey);
T entity; if (aLock) {
entity = _session.load(getEntityClass(), aPrimaryKey, LockMode.UPGRADE);
} else
entity = _session.load(getEntityClass(), aPrimaryKey);
postLoad(entity);
return entity;
}
我的数据库版本是
基于x86_64-unknown-linux-gnu的PostgreSQL 9.4.4,由gcc(Debian)编译
4.9.2-10)4.9.2,64位
我用
hibernate-core-3.6.0.Final.jar
我的实体类如下所示(几乎没有其他字段):
我将
birthdate
字段的类型更改为timestamtz
——然后一切看起来都很正常。但是如何在不改变列的数据类型的情况下解决这个问题呢?你有什么建议吗?我想问题可能是你的系统设置为CET
,但波兰目前是CEST
(Pg荣誉DST)
您可以做以下几件事:
- 使用
设置时区时区在每个会话开始时使用code>以确保它与您的客户端匹配
- 选择值时使用时区
或功能
,以匹配客户端时区(区域,时间戳)
- 选择时将值强制转换为
,以便保留TZ信息(实际上不确定此信息)timestamptz
timestamptz
来存储时间要好得多
要回答评论中的问题,只需将timestamp/tz
值转换为date
类型(birthdate::date
)<代码>日期s没有时间信息,并且不依赖于时区,因此您将始终按原样获取值
这实际上可能更有意义-您可能希望看到原始时区中的出生日期(即用户输入的日期),而不是转换为当前的TZ。PG如何将其存储为时间戳而不是日期?奇怪的您可以更改列定义以将其存储为日期而不是时间戳吗?@NeilMcGuigan我可以,但数据库中已经有几千个用户,因此我必须更改所有用户的出生日期(我将在PostgreSQL中检查日期与时间戳的区别,因为我不确定如何在这两种类型之间转换)。
import javax.persistence.Column;
@javax.persistence.Entity
@javax.persistence.Table(name="User")
@javax.persistence.SequenceGenerator(name="userId", sequenceName="user_id_seq", allocationSize=1)
public class User {
@javax.persistence.Id
@Column(name="Id", nullable=false)
@javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO, generator="userId")
private long id;
@Column(name="Name")
private String firstName;
public User(String firstName, java.util.Date birthDate, java.util.Date registrationDate)
{
this.firstName = firstName;
this.birthDate = birthDate;
this.registrationDate = registrationDate;
}
@Column(name="BirthDate")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private java.util.Date birthDate;
@Column(name="RegistrationDate", nullable=false)
@javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP)
private java.util.Date registrationDate;
public String toString()
{
return firstName + " should clean himself...";
}
public User() {}
}