Hibernate在将Java日历对象读写到SQL时间戳时使用哪个时区?
将Java对象写入SQL列时,它会将日期、计算机日期或日历对象(或其他)中指定的日期调整到哪个时区 当Hibernate将时间戳读入calendar对象时,它将日期转换到哪个时区 当Hibernate将Java日历对象写入SQL时间戳列时,它会将日期、计算机日期或日历对象(或其他)中指定的日期调整到哪个时区 Hibernate 3.x在Hibernate在将Java日历对象读写到SQL时间戳时使用哪个时区?,java,sql,hibernate,timestamp,Java,Sql,Hibernate,Timestamp,将Java对象写入SQL列时,它会将日期、计算机日期或日历对象(或其他)中指定的日期调整到哪个时区 当Hibernate将时间戳读入calendar对象时,它将日期转换到哪个时区 当Hibernate将Java日历对象写入SQL时间戳列时,它会将日期、计算机日期或日历对象(或其他)中指定的日期调整到哪个时区 Hibernate 3.x在日历类型中使用以下内容(请参阅): 所以Hibernate使用日历的时区 当Hibernate将时间戳读入calendar对象时,它将日期转换到哪个时区 好的,再
日历类型中使用以下内容(请参阅):
所以Hibernate使用日历的时区
当Hibernate将时间戳读入calendar对象时,它将日期转换到哪个时区
好的,再次让我们看看CalendarType
类:
public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
Timestamp ts = rs.getTimestamp(name);
if (ts!=null) {
Calendar cal = new GregorianCalendar();
if ( Environment.jvmHasTimestampBug() ) {
cal.setTime( new Date( ts.getTime() + ts.getNanos() / 1000000 ) );
}
else {
cal.setTime(ts);
}
return cal;
}
else {
return null;
}
}
因此,Hibernate使用默认时区中的当前时间和默认语言环境构建一个默认的GregoriaCalendar
作为旁注,我强烈建议阅读以下问题:
我刚刚花了6个小时在一个类似的问题上,我想我会在这里记录下来。Hibernate确实使用JVM时区,但可以通过如下扩展日历类型来更改它:
public class UTCCalendarType extends CalendarType {
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
/**
* This is the original code from the class, with two changes. First we pull
* it out of the result set with an example Calendar. Second, we set the new
* calendar up in UTC.
*/
@Override
public Object get(ResultSet rs, String name) throws SQLException {
Timestamp ts = rs.getTimestamp(name, new GregorianCalendar(UTC));
if (ts != null) {
Calendar cal = new GregorianCalendar(UTC);
cal.setTime(ts);
return cal;
} else {
return null;
}
}
@Override
public void set(PreparedStatement st, Object value, int index) throws SQLException {
final Calendar cal = (Calendar) value;
cal.setTimeZone(UTC);
st.setTimestamp(index, new Timestamp(cal.getTime().getTime()), cal);
}
}
这里的秘方是:
rs.getTimestamp(name, new GregorianCalendar(UTC));
这会将时区从结果集转换为所需的任何时区。因此,我所做的就是将这种类型与任何UTC日历和本地时间的标准Hibernate类型一起使用。工作起来很流畅…如果您不想自己编写代码,可以使用开源库DbAssist
。应用此修复后,数据库中的日期将由JDBC处理,然后作为UTC休眠,因此您甚至不必更改entitiy类
例如,如果您在Hibernate 4.3.11中使用JPA注释,请添加以下Maven依赖项:
<dependency>
<groupId>com.montrosesoftware</groupId>
<artifactId>DbAssist-4.3.11</artifactId>
<version>1.0-RELEASE</version>
</dependency>
如果您想了解有关如何为不同的Hibernate版本(或HBM文件)应用修复程序的更多信息,请参阅。您还可以在本文中阅读有关时区转换问题的更多信息。默认情况下,由JDBC驱动程序决定使用哪个时区。通常,除非将JDBC驱动程序配置为使用自定义时区,否则将使用JVM时区
如果要控制使用的时区,可以在JVM级别设置时区。如果希望JVM时区与数据库使用的时区不同,则需要使用Hibernate 5.2配置属性:
<property name="hibernate.jdbc.time_zone" value="US/Eastern"/>
相关问题:似乎提供了解决方案。回答得不错!直接从“源头”!出于好奇,代码所指的JVM时间戳bug是什么?@Derek thejavadoc说这个JVM有IBMJDK1.3.1吗。错误是newtimestamp(x).getTime()=x
。有趣的是,与您引用的版本相比,Hibernate类型类的当前版本更通用,更不直接(因此,更难理解)。不过,基本的最低级别代码基本相同,只是现在Hibernate不再将日历传递给setTimestamp()
。虽然在的文档中没有说明,但我猜此方法仍然使用默认时区。@Derek您指的是什么“当前”版本,3.6.0.Final?它只是创建一个日历,默认情况下使用默认时区。您所要做的就是将日历
对象上的时区更改为您喜欢的任何时区。内部存储器只是一个毫秒计数器。更改时区只会导致日历上的get
方法以不同方式转换毫秒。您好@markthegrea,hibernate是否需要进行任何配置更改,以使hibernate采用自定义UTCCalendarType而不是基类CalendarType?非常感谢。。。耶。。!!!是的!
<property name="createdAt" type="com.montrosesoftware.dbassist.types.UtcDateType" column="created_at"/>
<property name="hibernate.jdbc.time_zone" value="US/Eastern"/>