Podpora JPA 2.2 pre typy dátumu a času Java 8
1. Prehľad
Verzia JPA 2.2 oficiálne predstavila podporu pre Java 8 Dátum a Čas API. Predtým sme sa buď museli spoliehať na proprietárne riešenie, alebo sme museli použiť rozhranie API JPA Converter.
V tomto návode ukážeme si, ako mapovať rôzne Java 8 Dátum a Čas typy. Špeciálne sa zameriame na tie, ktoré zohľadňujú informácie o ofsetu.
2. Maven závislosti
Predtým, ako začneme, musíme do triedy projektu zahrnúť API JPA 2.2. V projekte založenom na Maven môžeme jednoducho pridať jeho závislosť k našej pom.xml spis:
javax.persistence javax.persistence-api 2.2
Na spustenie projektu navyše potrebujeme implementáciu JPA a ovládač JDBC databázy, s ktorou budeme pracovať. V tomto tutoriále budeme používať EclipseLink a databázu PostgreSQL:
org.eclipse.persistence eclipselink 2.7.4 runtime org.postgresql postgresql 42.2.5 runtime zväzok
Neváhajte a pozrite si najnovšie verzie rozhrania JPA API, EclipseLink a ovládača PostgreSQL JDBC na serveri Maven Central.
Samozrejme môžeme použiť aj iné databázy alebo implementácie JPA, ako je napríklad Hibernate.
3. Podpora TimeZone
Môžeme pracovať s ľubovoľnou databázou, ale najskôr by sme mali skontrolovať podporu pre tieto štandardné typy SQL, pretože JDBC 4.2 je založený na:
- ČASOVÁ ZNÁMKA (n) S ČASOVOU ZÓNOU
- ČASOVKA (n) BEZ ČASOVEJ ZÓNY
- ČAS (n) S ČASOVOU ZÓNOU
- ČAS (n) BEZ ČASOVEJ ZÓNY
Tu, n je presnosť zlomkových sekúnd a je medzi 0 a 9 číslicami. BEZ ČASOVEJ ZÓNY je voliteľné a možno ho vynechať. Ak S ČASOVOU ZÓNOU je zadaný, je vyžadovaný názov časovej zóny alebo posunutie voči UTC.
Časové pásmo môžeme reprezentovať v jednom z týchto dvoch formátov:
- Názov časovej zóny
- Ofset z UTC alebo písmeno Z pre UTC
Pre náš príklad sme si vybrali databázu PostgreSQL vďaka jej plnej podpore pre typ SQL ČAS S ČASOVOU ZÓNOU.
Upozorňujeme, že iné databázy nemusia podporovať tieto typy.
4. Mapovanie typov dátumov pred jazykom Java 8
Pred jazykom Java 8 sme zvyčajne museli mapovať všeobecné typy SQL ČAS, DÁTUMa ČASOVÁ ZNAČKA, buď do java.sql. * triedy java.sql.Time, java.sql.Date, a java.sql.Timestamp, respektíve alebo do java.util typy java.util.Date a java.util.Calendar.
Najprv sa pozrime, ako používať java.sql typy. Tu jednoducho definujeme atribúty pomocou java.sql typy ako súčasť @Entity trieda:
@Entity verejná trieda JPA22DateTimeEntity {private java.sql.Time sqlTime; private java.sql.Date sqlDate; súkromná java.sql.Timestamp sqlTimestamp; // ...}
Kým java.sql typy fungujú ako všetky ostatné typy bez ďalšieho mapovania, java.util typy musia špecifikovať zodpovedajúce časové typy.
To sa deje prostredníctvom @ Temporal anotácia ktorej hodnotu Atribút nám umožňuje určiť zodpovedajúci typ JDBC pomocou znaku TemporalType vyčíslenie:
@Temporal (TemporalType.TIME) private java.util.Date utilTime; @Temporal (TemporalType.DATE) súkromné java.util.Date utilDate; @Temporal (TemporalType.TIMESTAMP) súkromná java.util.Date utilTimestamp;
Upozorňujeme, že ak ako implementáciu používame režim dlhodobého spánku, nepodporuje to mapovanie Kalendár do TIME.
Podobne môžeme použiť Kalendár trieda:
@Temporal (TemporalType.TIME) súkromný kalendár calendarTime; @Temporal (TemporalType.DATE) súkromný kalendár CalendarDate; @Temporal (TemporalType.TIMESTAMP) súkromný kalendár CalendarTimestamp;
Žiadny z týchto typov nemá podporu pre časové pásmo alebo posunutie. Aby sme sa s týmito informáciami vysporiadali, museli sme si tradične ukladať čas UTC.
5. Mapovanie typov dátumov Java 8
Java 8 predstavila java.time balíkov a rozhranie JDBC 4.2 API pridalo podporu pre ďalšie typy SQL ČASOVÁ ZNÁMKA S ČASOVOU ZÓNOU a ČAS S ČASOVOU ZÓNOU.
Teraz môžeme mapovať typy JDBC ČAS, DÁTUM, a ČASOVÁ ZNAČKA do java.time typy – Miestny čas,LocalDatea LocalDateTime:
@Column (name = "local_time", columnDefinition = "TIME") private LocalTime localTime; @Column (name = "local_date", columnDefinition = "DATE") private LocalDate localDate; @Column (name = "local_date_time", columnDefinition = "TIMESTAMP") private LocalDateTime localDateTime;
Ďalej máme podporu pre posunutú miestnu časovú zónu na UTC cez Čas posunu a OffsetDateTime triedy:
@Column (name = "offset_time", columnDefinition = "ČAS S ČASOVOU ZÓNOU") private OffsetTime offsetTime; @Column (name = "offset_date_time", columnDefinition = "TIMESTAMP S ČASOVOU ZÓNOU") private OffsetDateTime offsetDateTime;
Zodpovedajúce mapované typy stĺpcov by mali byť ČAS S ČASOVOU ZÓNOU a ČASOVÁ ZNÁMKA S ČASOVOU ZÓNOU. Nie všetky databázy bohužiaľ tieto dva typy podporujú.
Ako vidíme, JPA podporuje týchto päť tried ako základné typy a na rozlíšenie medzi dátumom a / alebo časom nie sú potrebné žiadne ďalšie informácie.
Po uložení novej inštancie našej triedy entít môžeme skontrolovať, či boli údaje vložené správne:

6. Záver
Pred programami Java 8 a JPA 2.2 museli vývojári zvyčajne prevádzať typy dátumu a času na UTC, aby ich mohli uchovať. JPA 2.2 teraz podporuje túto funkciu po vybalení z krabice podporou posunu do UTC a využitím podpory JDBC 4.2 pre časové pásmo.
Celý zdrojový kód pre tieto vzorky nájdete na stránkach Github.