A dolgok jelenlegi állása idővel
A JDBC feltalálása és interfészeinek szabványosítása óta 20 év telt el, és ezalatt sok minden megváltozott.
Először is, a világ globálissá vált, és most egyetlen szerver képes kiszolgálni a felhasználókat a világ minden tájáról. Növekszik az internet sebessége. Ezért egy másik adattípus került az SQL-be, hogy az idővel működjön. A típusok most így néznek ki:
- DÁTUM – tárolja a dátumot: év, hónap, nap.
- IDŐ – tárolja az időt: órák, percek, másodpercek.
- TIMESTAMP – egy adott időpontot tárol: dátum, idő és ezredmásodperc.
- IDŐBÉLYEG IDŐZÓVAL - IDŐBÉLYEGZET és időzóna (zóna neve vagy eltolás).
Másodszor, a Java bevezette a DateTime API-t a globális időkezeléshez. A következő osztályokkal rendelkezik:
- Dátum és idő :
- LocalDate
- Helyi idő
- Pontos pillanat :
- java.time.Instant
- java.time.LocalDateTime
- java.time.OffsetDateTime
- java.time.ZonedDateTime
- Idő az időzónával :
- java.time.OffsetDateTime
- java.time.ZonedDateTime
A harmadik érdekesség az, hogy sok SQL kliens szeretne időt kapni a helyi zónájában lévő szervertől . Természetesen menet közben is át lehet konvertálni az időt, de ez nem kényelmes, és vannak hibák.
Például a mai nap összes feladatát szeretném lekérni az adatbázisból. Az SQL Server rendelkezik erre a CURDATE() függvényrel. Csak itt a szerver az USA-ban van, én pedig Japánban. És szeretném, ha visszaadná az összes lemezt az „én mai napom” címére, és nem „az övé a mai”.
Általánosságban elmondható, hogy az SQL szervernek képesnek kell lennie arra is, hogy okosan működjön együtt a különböző időzónákban lévő ügyfelekkel.
A modern problémák modern megoldásokat igényelnek
Elvileg a Java DateTime API új típusai és az SQL-ből származó típusok kényelmesen leképezhetők. A DATE típus Java-ban való megjelenítéséhez a java.time.LocalDate osztályt kell használnia a JDK 8 DateTime API-ból.
Az adatbázisból származó TIME típust két Java típus képviselheti: java.time.LocalTime és java.time.OffsetTime . Semmi bonyolult sem.
Egy adott időpont, amelyet az adatbázisban a TIMESTAMP típus képvisel , a Java nyelven 4 típussal ábrázolható:
- java.time.Instant
- java.time.LocalDateTime
- java.time.OffsetDateTime
- java.time.ZonedDateTime
És végül, az IDŐZÓNA IDŐBÉLYEGZÉS kétféleképpen ábrázolható:
- java.time.OffsetDateTime
- java.time.ZonedDateTime
Mivel már ismeri a DateTime API-t, nem lesz nehéz megjegyezni ezt a dolgot :)
Leírom táblázat formájában, így könnyebb lesz:
SQL TÍPUS | Java típus |
---|---|
DÁTUM | java.time.LocalDate |
IDŐ | java.time.LocalTime java.time.OffsetTime |
IDŐBÉLYEG | java.time.Instant java.time.LocalDateTime java.time.OffsetDateTime java.time.ZonedDateTime |
IDŐBÉLYEG IDŐZÓNÁVAL | java.time.OffsetDateTime _ |
A dátum megszerzése
Van egy jó hírem számodra. Hosszú idő óta először. Megkerülhetjük a getDate() metódus korlátozását , amely java.sql dátumtípust ad vissza.
A lényeg az, hogy a tárgyeredménykészletvan egy másik érdekes módszer - getObject() . Ez a metódus két paramétert vesz fel: egy oszlopot és egy típust, és az oszlop adott típusra konvertált értékét adja vissza. A módszer általános formája a következő:
ClassName Name = getObject(column, ClassName);
Ha pedig a DATE típust java.time.LocalDate típusra szeretné konvertálni , akkor valami ilyesmit kell írnia:
LocalDate localDate = results.getObject(4, LocalDate.class);
És általában minden TIMESTAMP átalakítható egy csomó típusra:
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);
Fontos! Ez a kód nem fog működni, ha elavult MySQL JDBC illesztőprogramja van . Ügyeljen a „mysql-connector-java” pom.xml fájlba írt verziójára, vagy a projektbeállítások könyvtáraihoz adott verziójára.
Egyébként ugyanígy megkerülhető a primitív típusok null tárolásának képtelensége is. Ha egy táblázat oszlopa INT típusú, akkor több módon is null értéket kaphatunk belőle. Lásd az alábbi példát:
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
Időzóna beállítása a MySQL-ben
A MySQL-lel is sok érdekes dolog történt. Mint tudod, a MySQL-kapcsolat létrehozásakor különféle paramétereket adhat hozzá :mysql://localhost:3306/db_scheme?Name=meaning&Name=meaning
Tehát három paramétert adtunk hozzá az időzónákkal való együttműködéshez a MySQL-ben. Ezeket a paramétereket átadhatja, amikor kapcsolatot létesít a szerverrel.
Az alábbiakban adok egy táblázatot velük:
Paraméter | Értékek | Alapértelmezett érték |
---|---|---|
connectTimeZone | HELYI | SZERVER | felhasználói zóna | SZERVER |
forceConnectionTimeZoneToSession | igaz | hamis | igaz |
KeepInstants | igaz | hamis | hamis |
A connectionTimeZone paraméter segítségével kiválasztjuk azt az időzónát (időzónát), amelyben az összes kérés végrehajtásra kerül. A kliens szempontjából a szerver a megadott időzónában fut.
A forceConnectionTimeZoneToSession paraméter hatására a rendszer figyelmen kívül hagyja a session time_zone változót, és a connectTimeZone-ra cseréli.
Végül a konservInstants paraméter vezérli a pontos idő-konverziót a JVM időzónája és a connectionTimeZone között.
A leggyakoribb konfigurációk a következők:
-
connectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=false – a régi MySQL JDBC illesztőprogram 5.1-es verziójának felel meg, ahol useLegacyDatetimeCode=true.
-
connectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=true egy új mód, amely a dátum- és időértékek kezelésének legtermészetesebb módját biztosítja.
-
connectionTimeZone=SZERVER & konservInstants=true – Megfelel a régi MySQL JDBC illesztőprogram 5.1-es verziójának, a useLegacyDatetimeCode=false értékkel.
-
connectionTimeZone=user_defined & konservInstants=true – Segít leküzdeni azt a helyzetet, amikor a kiszolgáló időzónáját nem ismeri fel az összekötő, mert az általános rövidítésként van beállítva, például CET/CEST.
Igen, a dátumok érdekes téma, és sok probléma van velük. Ahogy a mondás tartja: ijesztő persze, de én sem vagyok mérges! :)
GO TO FULL VERSION