Thêm một câu trả lời hoàn toàn dựa trên và mắc nợ để thoái vốn với gợi ý từ Shaun Stone. Tôi chỉ muốn giải thích nó một cách chi tiết vì nó là một vấn đề phổ biến và giải pháp hơi khó hiểu.
Điều này đang sử dụng Hibernate 4.1.4.Final, mặc dù tôi nghi ngờ bất cứ điều gì sau 3.6 sẽ hoạt động.
Đầu tiên, tạo UtcTimestampTypeDescriptor của divestoclimb
public class UtcTimestampTypeDescriptor extends TimestampTypeDescriptor {
public static final UtcTimestampTypeDescriptor INSTANCE = new UtcTimestampTypeDescriptor();
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
st.setTimestamp( index, javaTypeDescriptor.unwrap( value, Timestamp.class, options ), Calendar.getInstance(UTC) );
}
};
}
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap( rs.getTimestamp( name, Calendar.getInstance(UTC) ), options );
}
};
}
}
Sau đó, tạo UtcTimestampType, sử dụng UtcTimestampTypeDescriptor thay vì TimestampTypeDescriptor làm SqlTypeDescriptor trong lệnh gọi hàm tạo siêu cấp nhưng nếu không sẽ ủy quyền mọi thứ cho TimestampType:
public class UtcTimestampType
extends AbstractSingleColumnStandardBasicType<Date>
implements VersionType<Date>, LiteralType<Date> {
public static final UtcTimestampType INSTANCE = new UtcTimestampType();
public UtcTimestampType() {
super( UtcTimestampTypeDescriptor.INSTANCE, JdbcTimestampTypeDescriptor.INSTANCE );
}
public String getName() {
return TimestampType.INSTANCE.getName();
}
@Override
public String[] getRegistrationKeys() {
return TimestampType.INSTANCE.getRegistrationKeys();
}
public Date next(Date current, SessionImplementor session) {
return TimestampType.INSTANCE.next(current, session);
}
public Date seed(SessionImplementor session) {
return TimestampType.INSTANCE.seed(session);
}
public Comparator<Date> getComparator() {
return TimestampType.INSTANCE.getComparator();
}
public String objectToSQLString(Date value, Dialect dialect) throws Exception {
return TimestampType.INSTANCE.objectToSQLString(value, dialect);
}
public Date fromStringValue(String xml) throws HibernateException {
return TimestampType.INSTANCE.fromStringValue(xml);
}
}
Cuối cùng, khi bạn khởi tạo cấu hình Hibernate của mình, hãy đăng ký UtcTimestampType dưới dạng ghi đè kiểu:
configuration.registerTypeOverride(new UtcTimestampType());
Giờ đây, dấu thời gian không nên quan tâm đến múi giờ của JVM trên đường đến và đi từ cơ sở dữ liệu. HTH.