Comment spécifier le fuseau horaire UTC pour le Printemps de Démarrage JPA Timestamp
Environnement
- Printemps de Démarrage Démarreur de Données JPA 1.4.2
- Eclipselink 2.5.0
- Postgresql 9.4.1211.jre7
Problème
Je suis la construction d'un Printemps de Démarrage microservice qui partage une base de données Postgresql avec un autre service. La base de données est initialisé à l'extérieur (hors de notre contrôle) et la colonne datetime type utilisé par l'autre service est timestamp sans fuseau horaire. Donc, puisque je veux que toutes les dates sur le db d'avoir le même type, ayant ce type est une exigence pour mon entité JPA dates.
La façon dont je carte sur mon JPA objets de l'entité est comme suit:
@Column(name = "some_date", nullable = false)
private Timestamp someDate;
Le problème est que lorsque je crée un Timestamp comme suit:
new java.sql.Timestamp(System.currentTimeMillis())
et je regarde la base de données, l'horodatage contient mon fuseau horaire local de date, mais je veux le ranger en UTC. C'est parce que mon Fuseau horaire par défaut est réglé à "l'Europe de Bruxelles" et JPA/JDBC convertit mon java.sql.Timestamp
objet dans mon fuseau horaire avant de les mettre dans la base de données.
Trouve pas de solutions idéales
TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
a l'effet que je veux obtenir, mais il n'est pas approprié parce qu'il n'est pas spécifique à mon service. I. e. il aura une incidence sur l'ensemble de la JVM ou le thread en cours plus les enfants.- Démarrage de l'application avec
-Duser.timezone=GMT
semble aussi faire le travail pour une seule instance de l'exécution de la JVM. Par conséquent, une solution meilleure que la précédente.
Mais est-il un moyen de spécifier le fuseau horaire à l'intérieur de la JPA/source de données/printemps de configuration de démarrage?
Merci de répondre à @Adam, je viens de
SELECT * FROM my_table
. Selon la réponse que vous avez lié, "quand on plus tard affichage d'horodatage, vous obtenez ce que vous avez entré littéralement". Si je SELECT my_timestamp AT TIME ZONE 'UTC' AT TIME ZONE 'UTC' FROM my_table
je vois le même résultat, ce qui est logique. Considérant que, je suppose qu'il n'est pas PostgreSQL réglage du fuseau horaire, l'ajustement semble se produire avant que la valeur est dans la db sur le Java côté.OriginalL'auteur oizulain | 2017-01-12
Vous devez vous connecter pour publier un commentaire.
Les plus appropriées à la solution de contournement j'ai pu comprendre que le problème est d'utiliser un
AttributeConverter
pour convertir Java 8ZonedDateTime
objets dansjava.sql.Timestamp
objets, de sorte qu'ils peuvent être mappées à l'PostgreSQLtimestamp without time zone
type.La raison pour laquelle vous avez besoin d'un
AttributeConverter
est parce que le Java 8/Joda time date du temps des types de ne sont pas encore compatibles avec JPA.La
AttributeConverter
ressemble à ceci:Cela me permet de lire la base de données d'horodatages ne pas avoir des informations sur le fuseau horaire que
ZonedDateTime
objets qui ont le UTC fuseau horaire. De cette façon, je garde la date exacte de temps qui peut être vu sur la db quel que soit le fuseau horaire que mon application s'exécute dans l'.Depuis
toLocalDateTime()
aussi s'applique le système du fuseau horaire par défaut de conversion, ceAttributeConverter
fondamentalement annule la conversion appliquée par le pilote JDBC.Avez-vous vraiment besoin d'utiliser
timestamp without timezone
?La réalité est que si vous stockez de la date de l'information en temps sur un fuseau horaire (même si il est UTC), le
timestamp without timezone
PostgreSQL type est le mauvais choix. Le bon type de données à utiliser seraittimestamp with timezone
qui inclut les informations de fuseau horaire. Plus sur ce sujet ici.Toutefois, si pour quelque raison que ce soit, vous doit utiliser le
timestamp without timezone
, je pense que leZonedDateTime
approche ci-dessus est un appareil robuste et cohérente de la solution.Vous êtes à la sérialisation de l'
ZonedDateTime
en JSON?Alors vous êtes probablement intéressé par le fait que vous devez avoir au moins la version
2.6.0
de lajackson-datatype-jsr310
de dépendance pour la sérialisation de travail. Plus sur que dans cette réponse.OriginalL'auteur oizulain
Vous ne pouvez pas. Eclipselink utilise le seul arg version de
setTimestamp
, une délégation de la responsabilité pour le temps de la zone de manutention pour le pilote et le pilote jdbc postgresql n'autorise pas le fuseau horaire par défaut pour être substituée. La postgres pilote même se propage le client de fuseau horaire pour la session, donc côté serveur par défaut seront d'aucune utilité pour vous.Il y a quelques hackish choses que vous pourriez essayer de contourner le problème, par exemple la rédaction d'un JPA 2.1
AttributeConverter
de changer votre horodateurs dans la destination de la zone, mais en fin de compte ils sont condamnés parce que votre client le fuseau horaire de l'heure d'été ajustements, rendant ainsi certains moments ambigus ou irreprésentable.Vous devrez définir le fuseau horaire par défaut de votre client, ou de tomber dans natif SQL pour définir les horodatages comme des chaînes de caractères avec des moulages.
OriginalL'auteur teppic