4.1 Kirándulás a történelembe
A Java objektumok adatbázisba mentése szinte azonnal aktuális volt a Java nyelv létrehozása után. Ekkor a Java nyelvben egyetlen adattípus volt, a Date, amely a UNIX-időszabvány szerint tárolta az időt: ezredmásodpercek száma 1970 óta.
Nos, az adatbázisokban akkoriban már különböző adattípusok voltak a dátumokhoz, legalábbis a dátumnak, az időnek és a dátum + időnek volt külön típusa:
- DÁTUM
- IDŐ
- IDŐBÉLYEG
Ezért a Java nyelv készítői egy speciális csomagot adtak hozzá - java.sql, amely osztályokat tartalmazott:
- java.sql.date
- java.sql.Time
- java.sql.timestamp
Ezeknek az osztályoknak a feltérképezése igazi öröm:
@Entity
public class TemporalValues {
@Basic
private java.sql.Date sqlDate;
@Basic
private java.sql.Time sqlTime;
@Basic
private java.sql.Timestamp sqlTimestamp;
}
De mivel korábban a programozók dolgoztak az osztállyal java.util.Date
, a Hibernate egy speciális megjegyzést adott hozzá @Temporal
a Dátum típus leképezésének vezérléséhez.
Példa:
// If the annotation is missing, then the database will have a TIMESTAMP type
Date dateAsTimestamp;
@Temporal(TemporalType.DATE) // will be mapped to DATE type
Date dateAsDate;
@Temporal(TemporalType.TIME) // will be mapped to TIME type
Date dateAsTime;
A típus java.util.Calendar
és az alapértelmezett típus a TIMESTAMPjava.util.Date
típust használja az adatbázisban való megjelenítésükhöz.
4.2 Új idő
Jelenleg a térképezéssel minden sokkal egyszerűbb és jobb. Minden adatbázis 4 típusú adatot támogat az idő függvényében:
- DATE - dátum: év, hónap és nap.
- IDŐ - idő: óra, perc, másodperc.
- TIMESTAMP – dátum, idő és nanoszekundum.
- IDŐBÉLYEG IDŐZÓVAL - IDŐBÉLYEGZET és időzóna (zóna neve vagy eltolás).
A típus képviseletére DÁTUMjava.time.LocalDate
Java-ban a JDK 8 DateTime API osztályát kell használnia .
típusIDŐaz adatbázisból kétféle típussal ábrázolható a Java-ból: java.time.LocalTime
és java.time.OffsetTime
. Semmi bonyolult.
És a típus által képviselt pontos dátum és időIDŐBÉLYEGaz alapban, Java-ban 4 típussal ábrázolható:
- java.time.Instant
- java.time.LocalDateTime
- java.time.OffsetDateTime
- java.time.ZonedDateTime
És végülIDŐBÉLYEG IDŐZÓNÁVALké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 :)
Feltérképezésük tiszta öröm:
@Basic
private java.time.LocalDate localDate;
@Basic
private java.time.LocalTime localTime;
@Basic
private java.time.OffsetTime offsetTime;
@Basic
private java.time.Instant instant;
@Basic
private java.time.LocalDateTime localDateTime;
@Basic
private java.time.OffsetDateTime offsetDateTime;
@Basic
private java.time.ZonedDateTime zonedDateTime;
A megjegyzés azt jelenti, hogy a mezőt automatikusan@Basic
fel kell dolgozni : a Hibernate eldönti, hogy melyik oszlopra és típusra legyen leképezve ez a mező.
4.3 Időzónák használata
Ha az időzóna egy dátum része, akkor ezek tárolása az adatbázisban egyszerű - akárcsak egy szokásos dátum:
@Basic
private java.time.OffsetDateTime offsetDateTime;
@Basic
private java.time.ZonedDateTime zonedDateTime;
Ha azonban az időzónákat a dátumtól elkülönítve szeretné tárolni:
@Basic
private java.time.TimeZone timeZone;
@Basic
private java.time.ZoneOffset zonedOffset;
Ezután a Hibernate alapértelmezés szerint VARCHAR típusban tárolja őket. Ami valójában logikus, mivel az Időzónának általában van egy karakterlánc neve, mint például "UTC + 3" vagy "Cairo".
4.4 Saját időzóna beállítása
Amikor a dátumok adatbázisba mentésével dolgozik, akkor szembesül azzal a ténnyel, hogy már 4 helyen állíthatja be az aktuális időzónát:
- Szerver operációs rendszer;
- DBMS;
- Java alkalmazás
- Hibernálás.
Ha a DBMS nem ad meg időzónát (TimeZone), akkor azt az operációs rendszer beállításaiból veszi. Ez kényelmetlen lehet, mivel a tartalék DBMS-ek gyakran más adatközpontokban találhatók, amelyek saját időzónával rendelkeznek.
Ezért szinte minden DBMS-adminisztrátor egyetlen zónát állít be, hogy az adatok könnyen átvihetők legyenek egyik szerverről a másikra.
Hasonló a helyzet egy Java alkalmazással is. Különböző adatközpontokban lévő különböző szervereken is futtatható, így általában van egy kifejezett időzóna.
java -Duser.timezone=UTC ...
Vagy miközben a program fut:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
És természetesen a Hibernate lehetővé teszi az időzóna explicit beállítását.
Először is a SessionFactory konfigurálásakor adható meg:
settings.put(
AvailableSettings.JDBC_TIME_ZONE,
TimeZone.getTimeZone("UTC")
);
Másodszor, az időzóna megadhatóegy adott munkamenethez:
Session session = sessionFactory()
.withOptions()
.jdbcTimeZone(TimeZone.getTimeZone("UTC"))
.openSession();
4.5 @TimeZoneStorage megjegyzés
Gyakran előfordul, hogy a programozók egy országban (és egy időzónában) történő munkavégzés alapján kezdtek el egy adatbázist tervezni, majd néhány év elteltével hozzá kellett adniuk a különböző időzónákban történő munkavégzés támogatását.
Ezért egyszerűen hozzáadtak egy külön oszlopot az adatbázishoz az időzóna tárolására. Ez olyan gyakori helyzet, hogy a Hibernate egy speciális megjegyzést adott hozzá, amely lehetővé teszi, hogy egy adott dátum időzónáját külön oszlopban tárolja.
Példa:
@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_offset_offset")
@Column(name = "birthday_offset")
private OffsetDateTime offsetDateTimeColumn;
@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_zoned_offset")
@Column(name = "birthday_zoned")
private ZonedDateTime zonedDateTimeColumn;
Ez egy mankó. De van rá mentség is: akkor jelent meg, amikor a DateTime API még nem létezett. Az időzónát pedig lehetetlen volt tárolni az osztályban java.util.Date
.
Nagyon remélem, hogy ezt nem fogja gyakran látni a kódjában.
GO TO FULL VERSION