Wie Sie angeben, UTC-Zeitzone für Spring-Boot-JPA-Timestamp
Umgebung
- Spring-Boot-Starter-Data-JPA 1.4.2
- Eclipselink 2.5.0
- Postgresql 9.4.1211.jre7
Problem
Ich bin Aufbau einer Spring-Boot-microservice, dass die Aktien einer Postgresql-Datenbank mit einem anderen Dienst. Die Datenbank wird initialisiert extern (außerhalb unserer Kontrolle) und die datetime-Spalte-Typ verwendet, durch die der andere Dienst ist Zeitstempel ohne Zeitzone. Also, da möchte ich alle Daten auf die db haben den gleichen Typ, mit diesem Typ ist eine Voraussetzung für meine JPA-Entität stammt.
Den Weg, den ich anzeigen auf meiner JPA-entity-Objekte ist wie folgt:
@Column(name = "some_date", nullable = false)
private Timestamp someDate;
Das problem ist, dass wenn ich einen Timestamp wie folgt:
new java.sql.Timestamp(System.currentTimeMillis())
und ich schaue auf die Datenbank, die den timestamp enthält meine lokale Zeitzone Datum Zeit, aber ich möchte, um es zu speichern in UTC. Dies ist, weil mein Standard-Zeitzone ist "Europe/Brussels" und JPA/JDBC wandelt meine java.sql.Timestamp
Objekt in meiner Zeitzone, bevor es in die Datenbank.
Fand nicht die ideale Lösung
TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
hat die Wirkung, die ich erreichen möchte, aber es ist nicht geeignet, da es nicht spezifisch zu meinem service. I. e. es wird Auswirkungen auf die gesamte JVM oder der aktuelle thread, plus Kinder.- Starten der Anwendung mit
-Duser.timezone=GMT
scheint auch die Arbeit zu tun für eine einzelne Instanz einer JVM ausgeführt. Daher eine bessere Lösung als die vorherigen.
Aber gibt es eine Möglichkeit zum festlegen der Zeitzone für die JPA/datasource/spring-boot-Konfiguration?
Vielen Dank für die Beantwortung @Adam, ich habe gerade
SELECT * FROM my_table
. Nach der Antwort, die Sie verknüpften, "wenn Sie später Anzeige, timestamp, Sie bekommen zurück, was Sie eingegeben haben buchstäblich". Wenn ich SELECT my_timestamp AT TIME ZONE 'UTC' AT TIME ZONE 'UTC' FROM my_table
sehe ich das gleiche Ergebnis, was Sinn macht. Wenn man bedenkt, dass, würde ich davon ausgehen, dass es nicht PostgreSQL einstellen der Zeitzone die Einstellung scheint zu passieren, bevor der Wert wird in die db auf der Java-Seite.InformationsquelleAutor oizulain | 2017-01-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die am besten geeignete Abhilfe konnte ich herausfinden, das problem ist die Verwendung einer
AttributeConverter
zu konvertieren Java 8ZonedDateTime
Objekte injava.sql.Timestamp
Objekte, so dass Sie zugeordnet werden können und die PostgreSQLtimestamp without time zone
geben.Den Grund, warum Sie benötigen eine
AttributeConverter
ist, weil der Java-8/Joda Zeit-Datum-Zeit-Typen sind noch nicht kompatibel mit JPA.Den
AttributeConverter
sieht wie folgt aus:Dies ermöglicht es mir zum Lesen der Datenbank timestamps nicht Zeitzonen Informationen wie
ZonedDateTime
Objekte, die UTC Zeitzone. Auf diese Weise halte ich das genaue Datum der Zeit, die gesehen werden kann auf die db unabhängig von der Zeitzone, die meine app läuft in.Seit
toLocalDateTime()
gilt auch für das system die default-Zeitzone-Konvertierung, dieseAttributeConverter
im Grunde bricht die Umwandlung der JDBC-Treiber.Tun, die Sie wirklich brauchen, zu verwenden
timestamp without timezone
?Die Realität ist, dass, wenn Sie die Speicherung von Datum, Uhrzeit einer Zeitzone (auch wenn es UTC)
timestamp without timezone
PostgreSQL-Typ ist die falsche Wahl. Den richtigen Datentyp zu verwenden ist, wäretimestamp with timezone
was beinhaltet die Zeitzone Informationen. Mehr zu diesem Thema hier.Jedoch, wenn aus irgendeinem Grund Sie muss verwenden Sie die
timestamp without timezone
ich denke, dieZonedDateTime
Ansatz oben ist eine robuste und konsistente Lösung.Sind Sie auch mit der Serialisierung der
ZonedDateTime
zu JSON?Dann sind Sie wahrscheinlich daran interessiert, die Tatsache, dass Sie benötigen mindestens die version
2.6.0
desjackson-datatype-jsr310
Abhängigkeit für die Serialisierung zu arbeiten. Mehr auf, dass in dieser Antwort.InformationsquelleAutor oizulain
Können Sie nicht. Eclipselink verwendet die single-arg-version von
setTimestamp
, das delegieren von Verantwortung für die Zeit-zone der Handhabung für den Fahrer, und die postgresql-jdbc-Treiber nicht zu, dass die Standard-Zeitzone zu überschreiben. Der postgres-Treiber sogar propagiert, die client-Zeitzone auf die Sitzung, damit server side defaults wird von keinerlei nutzen für Sie.Gibt es einige hackish Dinge, die Sie könnten versuchen, um das problem zu umgehen, zum Beispiel das schreiben einer JPA 2.1
AttributeConverter
zu verlagern Ihre Zeitstempel in der Ziel-zone, aber letztendlich sind Sie zum scheitern verurteilt, weil Sie Ihre client-Zeitzone Sommerzeit Anpassungen, so dass einige Male die zweideutige oder nichtdarstellbarer.Müssen Sie die Standard-Zeitzone auf deinem client, oder drop-in native-SQL-setzen von timestamps als String mit Gips.
InformationsquelleAutor teppic