Der aktuelle Stand der Dinge im Zeitverlauf

Seit der Erfindung von JDBC und der Standardisierung seiner Schnittstellen sind 20 Jahre vergangen und in dieser Zeit hat sich viel verändert.

Erstens ist die Welt global geworden und jetzt kann ein Server Benutzer aus der ganzen Welt bedienen. Die Internetgeschwindigkeit ist gestiegen. Daher wurde SQL ein weiterer Datentyp hinzugefügt, um mit der Zeit zu arbeiten. Nun sehen die Typen so aus:

  • DATUM – speichert das Datum: Jahr, Monat, Tag.
  • ZEIT – speichert die Zeit: Stunden, Minuten, Sekunden.
  • TIMESTAMP – speichert einen bestimmten Zeitpunkt: Datum, Uhrzeit und Millisekunden.
  • ZEITSTEMPEL MIT ZEITZONE – ZEITSTEMPEL und Zeitzone (Zonenname oder Offset).

Zweitens führte Java die DateTime-API für die globale Zeitverwaltung ein. Es gibt folgende Klassen:

  • Datum und Uhrzeit :
    • Lokales Datum
    • Ortszeit
  • Genauer Zeitpunkt :
    • java.time.Instant
    • java.time.LocalDateTime
    • java.time.OffsetDateTime
    • java.time.ZonedDateTime
  • Uhrzeit mit Zeitzone :
    • java.time.OffsetDateTime
    • java.time.ZonedDateTime

Der dritte interessante Punkt ist, dass viele SQL-Clients gerne Zeit vom Server erhalten möchten, der sich bereits in ihrer lokalen Zone befindet . Natürlich können Sie die Zeit im Handumdrehen umrechnen, aber das ist nicht praktisch und es gibt Fehler.

Ich möchte zum Beispiel alle Aufgaben für heute aus der Datenbank holen. SQL Server verfügt hierfür über eine CURDATE() -Funktion. Nur hier steht der Server in den USA und ich bin in Japan. Und ich möchte, dass er alle Datensätze für „mein Heute“ zurückgibt und nicht für „sein Heute“.

Generell muss der SQL-Server auch mit Clients in unterschiedlichen Zeitzonen intelligent zusammenarbeiten können.

Moderne Probleme erfordern moderne Lösungen

Grundsätzlich können neue Typen aus der Java DateTime API und Typen aus SQL komfortabel abgebildet werden. Um den DATE- Typ in Java darzustellen , müssen Sie die Klasse java.time.LocalDate aus der JDK 8 DateTime-API verwenden .

Der TIME-Typ aus der Datenbank kann durch zwei Typen aus Java dargestellt werden: java.time.LocalTime und java.time.OffsetTime . Auch nichts Kompliziertes.

Ein bestimmter Zeitpunkt, dargestellt durch den Typ TIMESTAMP in der Datenbank, kann in Java durch vier Typen dargestellt werden:

  • java.time.Instant
  • java.time.LocalDateTime
  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

Und schließlich kann TIMESTAMP WITH TIME ZONE durch zwei Typen dargestellt werden:

  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

Da Sie bereits mit der DateTime-API vertraut sind, wird es Ihnen nicht schwer fallen, sich an diese Angelegenheit zu erinnern :)

Ich werde es in Form einer Tabelle schreiben, damit es einfacher wird:

SQL-TYP Java-Typ
DATUM java.time.LocalDate
ZEIT java.time.LocalTime
java.time.OffsetTime
ZEITSTEMPEL java.time.Instant
java.time.LocalDateTime
java.time.OffsetDateTime
java.time.ZonedDateTime
ZEITSTEMPEL MIT ZEITZONE java.time.OffsetDateTime
_

Das Datum bekommen

Ich habe eine gute Nachricht für Sie. Zum ersten Mal seit langer Zeit. Wir können die Einschränkung der getDate()- Methode umgehen , die einen java.sql-Datumstyp zurückgibt.

Der Punkt ist, dass das ObjektErgebnissatzEs gibt noch eine weitere interessante Methode – getObject() . Diese Methode benötigt zwei Parameter: eine Spalte und einen Typ und gibt den Wert der in den angegebenen Typ konvertierten Spalte zurück. Die allgemeine Form der Methode ist wie folgt:

ClassName Name = getObject(column, ClassName);

Und wenn Sie den Typ DATE in den Typ java.time.LocalDate konvertieren möchten , müssen Sie etwas schreiben wie:

LocalDate localDate = results.getObject(4, LocalDate.class);

Und jeder TIMESTAMP im Allgemeinen kann in eine Reihe von Typen konvertiert werden:

java.time.Instant instant = results.getObject(9, java.time.Instant.class);
java.time.LocalDateTime local = results.getObject(9, java.time. LocalDateTime.class);
java.time.OffsetDateTime offset = results.getObject(9, java.time. OffsetDateTime.class);
java.time.ZonedDateTime zoned = results.getObject(9, java.time. ZonedDateTime.class);

Wichtig! Dieser Code funktioniert nicht, wenn Sie einen veralteten MySQL-JDBC-Treiber haben . Achten Sie auf die Version von „mysql-connector-java“, die in Ihrer pom.xml geschrieben oder in den Projekteinstellungen zu den Bibliotheken hinzugefügt wurde.

Auf die gleiche Weise können Sie übrigens die Unfähigkeit umgehen, null für primitive Typen zu speichern. Wenn eine Tabellenspalte vom Typ INT ist, gibt es mehrere Möglichkeiten, daraus Null zu erhalten. Siehe Beispiel unten:

Integer id1 = results.getObject(8, Integer.class);    	 // this will work
Integer id2 = results.getObject(8, int.class);                 //this will also work
int id3 = results.getObject(8,  Integer.class);            	//method will return null, JVM will throw NPE
int id4 = results.getObject(8,  int.class);                    	//method will return null, JVM will throw NPE

Zeitzoneneinstellung in MySQL

Auch mit MySQL sind viele interessante Dinge passiert. Wie Sie wissen, können Sie beim Erstellen einer MySQL-Verbindung verschiedene Parameter hinzufügen :
mysql://localhost:3306/db_scheme?Name=meaning&Name=meaning

Daher wurden drei Parameter hinzugefügt, um mit Zeitzonen in MySQL zu arbeiten. Sie können diese Parameter übergeben, wenn Sie eine Verbindung zum Server herstellen.

Nachfolgend werde ich eine Tabelle mit ihnen geben:

Parameter Werte Standardwert
ConnectionTimeZone LOKAL | SERVER | Benutzerzone SERVER
forceConnectionTimeZoneToSession wahr | FALSCH WAHR
PreserveInstants wahr | FALSCH FALSCH

Mit dem Parameter „connectionTimeZone“ wählen wir die Zeitzone (Zeitzone) aus, in der alle Anfragen ausgeführt werden. Aus Sicht des Clients läuft der Server in der angegebenen Zeitzone.

Der Parameter „forceConnectionTimeZoneToSession“ bewirkt, dass die Variable „session time_zone“ ignoriert und durch „connectionTimeZone“ ersetzt wird.

Schließlich steuert der Parameter „preserveInstants“ die exakte Zeitkonvertierung zwischen der timeZone und der ConnectionTimeZone der JVM.

Die häufigsten Konfigurationen sind:

  • ConnectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=false – entspricht der alten MySQL JDBC-Treiberversion 5.1 mit useLegacyDatetimeCode=true.

  • „connectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=true“ ist ein neuer Modus, der die natürlichste Möglichkeit bietet, Datums- und Uhrzeitwerte zu verarbeiten.

  • ConnectionTimeZone=SERVER & PreserveInstants=true – Entspricht der alten MySQL JDBC-Treiberversion 5.1 mit useLegacyDatetimeCode=false.

  • ConnectionTimeZone=user_definiert & PreserveInstants=true – hilft dabei, die Situation zu überwinden, in der die Zeitzone des Servers vom Connector nicht erkannt werden kann, weil sie als generische Abkürzung wie CET/CEST festgelegt ist.

Ja, Termine sind ein interessantes Thema und es gibt viele Probleme damit. Wie das Sprichwort sagt: Es ist natürlich gruselig, aber ich bin auch nicht sauer! :) :)