Slaapstand - Datum en tijd in kaart brengen

1. Inleiding

In dit artikel laten we zien hoe u tijdelijke kolomwaarden in Hibernate kunt toewijzen, inclusief de klassen van java.sql, java.util en java.time pakketjes.

2. Projectconfiguratie

Om de toewijzing van de tijdelijke typen te demonstreren, hebben we de H2-database en de nieuwste versie van de slaapstand-core bibliotheek:

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

Voor de huidige versie van het slaapstand-core bibliotheek, ga naar de Maven Central-repository.

3. Tijdzone instellen

Bij het omgaan met datums is het een goed idee om een ​​specifieke tijdzone in te stellen voor het JDBC-stuurprogramma. Op deze manier zou onze applicatie onafhankelijk zijn van de huidige tijdzone van het systeem.

Voor ons voorbeeld zullen we het per sessie instellen:

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

Een andere manier zou zijn om het slaapstand.jdbc.time_zone eigenschap in Hibernate-eigenschappenbestand dat wordt gebruikt om de session factory te bouwen. Op deze manier konden we de tijdzone één keer specificeren voor de hele applicatie.

4. In kaart brengen java.sql Types

De java.sql pakket bevat JDBC-typen die zijn uitgelijnd met de typen die zijn gedefinieerd door de SQL-standaard:

  • Datum komt overeen met de DATUM SQL-type, dat alleen een datum zonder tijd is
  • Tijd komt overeen met de TIJD SQL-type, een tijd van de dag gespecificeerd in uren, minuten en seconden
  • Tijdstempel bevat informatie over datum en tijd tot op nanoseconden nauwkeurig en komt overeen met de TIJDSTAMP SQL-type

Omdat deze typen in overeenstemming zijn met SQL, is hun toewijzing relatief eenvoudig. We kunnen ofwel de @Basic of de @Kolom annotatie:

@Entity openbare klasse TemporalValues ​​{@Basic privé java.sql.Date sqlDate; @Basic privé java.sql.Time sqlTime; @Basic privé java.sql.Timestamp sqlTimestamp; }

We zouden dan de corresponderende waarden als volgt kunnen instellen:

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

Merk op dat kiezen java.sql typen voor entiteitsvelden zijn misschien niet altijd een goede keuze. Deze klassen zijn JDBC-specifiek en bevatten veel verouderde functionaliteit.

5. In kaart brengen java.util.Date Type

Het type java.util.Date bevat zowel datum- als tijdinformatie, tot op de milliseconde nauwkeurig. Maar het heeft niet direct betrekking op een SQL-type.

Daarom hebben we nog een annotatie nodig om het gewenste SQL-type te specificeren:

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

De @Tijdelijk annotatie heeft de enkele parameterwaarde van type TemporalType. Het kan beide zijn DATUM, TIJD of TIJDSTAMP, afhankelijk van het onderliggende SQL-type dat we voor de mapping willen gebruiken.

We zouden dan de corresponderende velden als volgt kunnen instellen:

temporalValues.setUtilDate (nieuwe SimpleDateFormat ("jjjj-MM-dd"). parse ("2017-11-15")); temporalValues.setUtilTime (nieuwe SimpleDateFormat ("HH: mm: ss"). parse ("15:30:14")); temporalValues.setUtilTimestamp (nieuwe SimpleDateFormat ("jjjj-MM-dd HH: mm: ss.SSS") .parse ("2017-11-15 15: 30: 14.332"));

Zoals we hebben gezien, de java.util.Date type (milliseconden precisie) is niet nauwkeurig genoeg om de tijdstempelwaarde (nanoseconden precisie) te verwerken.

Dus wanneer we de entiteit uit de database halen, vinden we niet verrassend een java.sql.Timestamp bijvoorbeeld op dit gebied, zelfs als we aanvankelijk een java.util.Date:

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

Dit zou in orde moeten zijn voor onze code sinds Tijdstempel strekt zich uit Datum.

6. In kaart brengen java.util.Calendar Type

Net als bij de java.util.Date, de java.util.Calendar type kan worden toegewezen aan verschillende SQL-typen, dus we moeten ze specificeren met @Tijdelijk.

Het enige verschil is dat Hibernate geen mapping ondersteunt Kalender naar TIJD:

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

Hier is hoe we de waarde van het veld kunnen instellen:

Calendar 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. In kaart brengen java.time Types

Sinds Java 8 is de nieuwe Java Date and Time API beschikbaar voor het omgaan met tijdelijke waarden. Deze API lost veel van de problemen op van java.util.Date en java.util.Calendar klassen.

De soorten uit de java.time pakket worden direct toegewezen aan overeenkomstige SQL-typen. Het is dus niet nodig om expliciet te specificeren @Tijdelijk annotatie:

  • LocalDate is toegewezen aan DATUM
  • Lokale tijd en OffsetTime zijn toegewezen aan TIJD
  • Onmiddellijk, LocalDateTime, OffsetDateTime en ZonedDateTime zijn toegewezen aan TIJDSTAMP

Dit betekent dat we deze velden alleen kunnen markeren met @Basic (of @Kolom) annotatie, zoals deze:

@Basic privé java.time.LocalDate localDate; @Basic privé java.time.LocalTime localTime; @Basic privé java.time.OffsetTime offsetTime; @Basic privé java.time.Instant instant; @Basic privé java.time.LocalDateTime localDateTime; @Basic privé java.time.OffsetDateTime offsetDateTime; @Basic privé java.time.ZonedDateTime zonedDateTime;

Elke tijdelijke klasse in de java.time pakket heeft een static ontleden () methode om het verstrekte Draad waarde met behulp van het juiste formaat. Dus hier is hoe we de waarden van de entiteitsvelden kunnen instellen:

temporalValues.setLocalDate (LocalDate.parse ("2017-11-15")); 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 [Europe / Paris]"));

8. Conclusie

In dit artikel hebben we laten zien hoe u tijdelijke waarden van verschillende typen in Hibernate in kaart kunt brengen.

De broncode voor het artikel is beschikbaar op GitHub.