Ajouter une réponse qui est complètement basé sur et redevable à divestoclimb avec une touche de Shaun Stone. Je voulais juste l'expliquer en détail car c'est un problème courant et la solution est un peu confuse.
J'utilise Hibernate 4.1.4.Final, mais je pense que tout ce qui est postérieur à la version 3.6 fonctionnera.
Tout d'abord, créez le descripteur UtcTimestampTypeDescriptor de 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 );
}
};
}
}
Ensuite, créez UtcTimestampType, qui utilise UtcTimestampTypeDescriptor au lieu de TimestampTypeDescriptor comme SqlTypeDescriptor dans l'appel du super constructeur, mais qui autrement délègue tout à 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);
}
}
Enfin, lorsque vous initialisez votre configuration Hibernate, enregistrez UtcTimestampType en tant que remplacement de type :
configuration.registerTypeOverride(new UtcTimestampType());
Maintenant, les timestamps ne devraient pas être concernés par le fuseau horaire de la JVM lors de leurs déplacements vers et depuis la base de données. HTH.
1 votes
La réponse de Vlad Mihalcea fournit une réponse mise à jour (pour Hibernate 5.2+)