Hibernate在读取和写入Java Calendar对象到SQL TIMESTAMP时使用的时区是什么?

Der*_*har 18 java sql timestamp hibernate

Hibernate Java Calendar对象写入 SQL TIMESTAMP列时,它会调整日期,计算机的日期或日历对象(或其他)中指定的日期?

当Hibernate TIMESTAMP到日历对象,以哪个时区并把它翻译的日期?

Pas*_*ent 16

当Hibernate将Java Calendar对象写入SQL TIMESTAMP列时,它会调整日期,计算机的日期或日历对象(或其他)中指定的日期?

Hiberante 3.x使用以下内容CalendarType(参见HB-1006):

public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
    final Calendar cal = (Calendar) value;
    //st.setTimestamp( index,  new Timestamp( cal.getTimeInMillis() ), cal ); //JDK 1.5 only
    st.setTimestamp( index,  new Timestamp( cal.getTime().getTime() ), cal );
}
Run Code Online (Sandbox Code Playgroud)

所以Hibernate使用PreparedStatement#setTimestamp(int, Timestamp, Calendar)它来使用日历的时区.

当Hibernate读TIMESTAMP到日历对象,以哪个时区并把它翻译的日期?

那么,让我们再来看看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;
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,Hibernate 使用默认时区使用默认时区中的当前时间构造默认值GregorianCalendar.


作为旁注,我强烈建议您阅读以下问题:


mar*_*rea 6

我只花了6个小时处理类似的问题,并认为我会在这里记录它.Hibernate确实使用了JVM时区,但可以通过扩展CalendarType来改变它,如下所示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的秘诀是:

  rs.getTimestamp(name, new GregorianCalendar(UTC));
Run Code Online (Sandbox Code Playgroud)

这会将时区从结果集转换为您想要的任何时区.所以我所做的是将此类型与任何UTC日历和当地时间的标准Hibernate类型一起使用.作为吹口哨工作...