Hibernate - mapiranje datuma i vremena

1. Uvod

U ovom ćemo članku pokazati kako mapirati vrijednosti vremenskih stupaca u hibernaciji, uključujući klase iz java.sql, java.util i java.vrijeme paketi.

2. Postavljanje projekta

Da bismo demonstrirali mapiranje vremenskih tipova, trebat će nam baza podataka H2 i najnovija verzija hibernacija-jezgra knjižnica:

 org.hibernate hibernate-core 5.4.12.Final com.h2database h2 1.4.194 

Za trenutnu verziju hibernacija-jezgra knjižnica, krenite prema središnjem spremištu Maven.

3. Postavljanje vremenske zone

Kad se bavite datumima, dobro je postaviti određenu vremensku zonu za JDBC upravljački program. Na taj bi način naša aplikacija bila neovisna o trenutnoj vremenskoj zoni sustava.

Za naš primjer postavit ćemo ga po sesiji:

session = HibernateUtil.getSessionFactory (). withOptions () .jdbcTimeZone (TimeZone.getTimeZone ("UTC")) .openSession ();

Drugi način bio bi postavljanje hibernate.jdbc.time_zone svojstvo u datoteci svojstava hibernacije koja se koristi za izgradnju tvornice sesija. Na taj bismo način mogli jednom odrediti vremensku zonu za cijelu aplikaciju.

4. Mapiranje java.sql Vrste

The java.sql paket sadrži JDBC tipove koji su usklađeni s vrstama definiranim SQL standardom:

  • Datum odgovara DATUM SQL tip, koji je samo datum bez vremena
  • Vrijeme odgovara VRIJEME SQL tip, a to je doba dana određeno u satima, minutama i sekundama
  • Vremenska oznaka uključuje podatke o datumu i vremenu s preciznošću do nanosekundi i odgovara VREMENSKI KAMP SQL tip

Kako su ove vrste u skladu s SQL-om, tako je i njihovo mapiranje relativno jednostavno. Možemo koristiti bilo koji @Osnovni, temeljni ili @Stupac napomena:

@ Entity javna klasa TemporalValues ​​{@Basic private java.sql.Date sqlDate; @Basic private java.sql.Time sqlTime; @Basic private java.sql.Timestamp sqlTimestamp; }

Tada bismo mogli postaviti odgovarajuće vrijednosti poput ove:

temporalValues.setSqlDate (java.sql.Date.valueOf ("15.11.2017.")); temporalValues.setSqlTime (java.sql.Time.valueOf ("15:30:14")); temporalValues.setSqlTimestamp (java.sql.Timestamp.valueOf ("2017-11-15 15: 30: 14.332"));

Imajte na umu da odabirom java.sql tipovi za polja entiteta ne moraju uvijek biti dobar izbor. Te su klase specifične za JDBC i sadrže puno zastarjelih funkcionalnosti.

5. Kartiranje java.util.Datum Tip

Tip java.util.Datum sadrži podatke o datumu i vremenu, do milisekunde preciznosti. Ali to se ne odnosi izravno na bilo koji SQL tip.

Zbog toga nam je potrebna još jedna napomena da odredimo željeni SQL tip:

@Basic @Temporal (TemporalType.DATE) private java.util.Date utilDate; @Basic @Temporal (TemporalType.TIME) privatni java.util.Date utilTime; @Basic @Temporal (TemporalType.TIMESTAMP) private java.util.Date utilTimestamp;

The @Temporal napomena ima jednostruku vrijednost parametra tipa TemporalType. Može biti i jedno i drugo DATUM, VRIJEME ili VREMENSKI KAMP, ovisno o osnovnom tipu SQL koji želimo koristiti za mapiranje.

Tada bismo mogli postaviti odgovarajuća polja ovako:

temporalValues.setUtilDate (novi SimpleDateFormat ("yyyy-MM-dd"). parse ("15.11.2017.")); temporalValues.setUtilTime (novi SimpleDateFormat ("HH: mm: ss"). parse ("15:30:14")); temporalValues.setUtilTimestamp (novi SimpleDateFormat ("yyyy-MM-dd HH: mm: ss.SSS") .parse ("15.11.2017 15:30: 14,332"));

Kao što smo vidjeli, the java.util.Datum vrsta (milisekundna preciznost) nije dovoljno precizna da obrađuje vrijednost vremenske oznake (preciznost nanosekundi).

Dakle, kada dohvatimo entitet iz baze podataka, ne iznenađuje da ćemo pronaći java.sql.Timestamp primjerice u ovom polju, čak i ako smo u početku postojali a java.util.Datum:

temporalValues ​​= session.get (TemporalValues.class, temporalValues.getId ()); assertThat (temporalValues.getUtilTimestamp ()) .isEqualTo (java.sql.Timestamp.valueOf ("2017-11-15 15: 30: 14.332"));

Ovo bi trebalo biti u redu za naš kôd od Vremenska oznaka proteže se Datum.

6. Kartiranje java.util.Kalendar Tip

Kao i kod java.util.Datum, java.util.Kalendar type može se preslikati na različite SQL tipove, pa ih moramo navesti s @Temporal.

Jedina je razlika što Hibernate ne podržava mapiranje Kalendar do VRIJEME:

@Basic @Temporal (TemporalType.DATE) private java.util.Calendar calendarDate; @Basic @Temporal (TemporalType.TIMESTAMP) private java.util.Calendar calendarTimestamp;

Evo kako možemo postaviti vrijednost polja:

Kalendar calendarDate = Calendar.getInstance (TimeZone.getTimeZone ("UTC")); calendarDate.set (Calendar.YEAR, 2017.); calendarDate.set (Calendar.MONTH, 10); calendarDate.set (Calendar.DAY_OF_MONTH, 15); temporalValues.setCalendarDate (calendarDate);

7. Mapiranje java.vrijeme Vrste

Od Jave 8, novi Java datum i vrijeme API dostupan je za rješavanje vremenskih vrijednosti. Ovaj API rješava mnoge probleme sustava java.util.Datum i java.util.Kalendar razreda.

Vrste iz java.vrijeme paket izravno se mapiraju u odgovarajuće SQL tipove. Dakle, nema potrebe izričito navesti @Temporal napomena:

  • LocalDate mapira se na DATUM
  • Lokalno vrijeme i OffsetTime mapiraju se na VRIJEME
  • Trenutak, LocalDateTime, OffsetDateTime i ZonedDateTime mapiraju se na VREMENSKI KAMP

To znači da ta polja možemo označiti samo s @Osnovni, temeljni (ili @Stupac) napomena, poput ove:

@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;

Svaka vremenska klasa u java.vrijeme paket ima statički raščlaniti () metoda za raščlanjivanje ponuđenog Niz vrijednost pomoću odgovarajućeg formata. Dakle, evo kako možemo postaviti vrijednosti polja entiteta:

temporalValues.setLocalDate (LocalDate.parse ("15.11.2017.")); temporalValues.setLocalTime (LocalTime.parse ("15:30:18")); temporalValues.setOffsetTime (OffsetTime.parse ("08: 22: 12 + 01: 00")); temporalValues.setInstant (Instant.parse ("2017-11-15T08: 22: 12Z")); temporalValues.setLocalDateTime (LocalDateTime.parse ("2017-11-15T08: 22: 12")); temporalValues.setOffsetDateTime (OffsetDateTime.parse ("2017-11-15T08: 22: 12 + 01: 00")); temporalValues.setZonedDateTime (ZonedDateTime.parse ("2017-11-15T08: 22: 12 + 01: 00 [Europa / Pariz]"));

8. Zaključak

U ovom smo članku pokazali kako mapirati vremenske vrijednosti različitih vrsta u hibernaciji.

Izvorni kôd članka dostupan je na GitHubu.