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á @Temporala 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.LocalDateJava-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.