Datumkartläggning

Tillgängliga

4.1 Utflykt till historien

Uppgiften att spara Java-objekt i databasen var relevant nästan omedelbart efter skapandet av Java-språket. På den tiden fanns det bara en datatyp i Java-språket, Date, som lagrade tid enligt UNIX-tidsstandarden: som antalet millisekunder sedan 1970.

Tja, i databaserna på den tiden fanns det redan olika datatyper för datum, åtminstone fanns det separata typer för datum, tid och datum + tid:

  • DATUM
  • TID
  • TIDSSTÄMPEL

Därför lade skaparna av Java-språket till ett speciellt paket till det - java.sql, som innehöll klasser:

  • java.sql.date
  • java.sql.Time
  • java.sql.timestamp

Att kartlägga dessa klasser är ett sant nöje:

@Entity
public class TemporalValues {

	@Basic
    private java.sql.Date sqlDate;

	@Basic
    private java.sql.Time sqlTime;

    @Basic
    private java.sql.Timestamp sqlTimestamp;
}

Men eftersom programmerare brukade arbeta med klassen java.util.Datelade Hibernate till en speciell anteckning @Temporalför att kontrollera mappningen av datumtypen.

Exempel:

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

Typen java.util.Calendaroch java.util.Datestandardtypen använder TIMESTAMP -typen för att representera dem i databasen.

4.2 Ny tid

För närvarande, med kartläggning, är allt mycket enklare och bättre. Alla databaser stöder 4 typer av data att arbeta med tiden:

  • DATUM - datum: år, månad och dag.
  • TID - tid: timmar, minuter, sekunder.
  • TIMESTAMP - datum, tid och nanosekunder.
  • TIDSTÄMPEL MED TIDZON - TIDSTÄMPEL och tidszon (zonnamn eller offset).

För att representera typen DATUMi Java måste du använda en klass java.time.LocalDatefrån JDK 8 DateTime API.

TypTIDfrån databasen kan representeras av två typer från Java: java.time.LocalTimeoch java.time.OffsetTime. Inget komplicerat.

Och exakt datum och tid som representeras av typenTIDSSTÄMPELi basen, i Java kan det representeras av 4 typer:

  • java.time.Instant
  • java.time.LocalDateTime
  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

Och slutligenTIDSTÄMPEL MED TIDZONkan representeras av två typer:

  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

Eftersom du redan är bekant med DateTime API kommer det inte att vara svårt för dig att komma ihåg denna fråga :)

Att kartlägga dem är rent nöje:

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

Anteckningen @Basicinnebär att fältet ska bearbetas automatiskt : Hibernate kommer att bestämma vilken kolumn och typ detta fält ska mappas.

4.3 Arbeta med tidszoner

Om tidszonen är en del av ett datum är det enkelt att lagra dem i databasen - precis som ett vanligt datum:

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;

Men om du vill lagra tidszoner separat från datumet:

@Basic
private java.time.TimeZone timeZone;

@Basic
private java.time.ZoneOffset zonedOffset;

Då lagrar Hibernate dem i VARCHAR-typ som standard. Vilket faktiskt är logiskt, eftersom TimeZone vanligtvis har ett strängnamn som "UTC + 3" eller "Cairo".

4.4 Ställa in din egen tidszon

När du arbetar med att spara datum till databasen kommer du att stöta på att det redan finns 4 platser där du kan ställa in aktuell tidszon:

  • Serveroperativsystem;
  • DBMS;
  • Java-applikation
  • Övervintra.

Om DBMS inte anger en tidszon (TimeZone), kommer den att ta den från operativsystemets inställningar. Detta kan vara obekvämt, eftersom backup-DBMS ofta finns i andra datacenter som har sin egen tidszon.

Därför ställer nästan alla DBMS-administratörer in en enda zon så att data enkelt kan överföras från en server till en annan.

Situationen är liknande med en Java-applikation. Den kan också köras på olika servrar i olika datacenter, så den har vanligtvis en explicit tidszon.

java -Duser.timezone=UTC ...

Eller medan programmet körs:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

Och naturligtvis låter Hibernate dig explicit ställa in din tidszon.

Först kan det specificeras när du konfigurerar SessionFactory:

settings.put(
    AvailableSettings.JDBC_TIME_ZONE,
    TimeZone.getTimeZone("UTC")
);

För det andra kan tidszonen specificerasför en specifik session:

Session session = sessionFactory()
    .withOptions()
    .jdbcTimeZone(TimeZone.getTimeZone("UTC"))
    .openSession();

4.5 @TimeZoneStorage-anteckning

Det händer ofta att programmerare började designa en databas baserad på att arbeta i ett land (och en tidszon), och sedan efter ett par år behövde de lägga till stöd för att arbeta i olika tidszoner.

Därför lade de helt enkelt till en separat kolumn i databasen för att lagra tidszonen. Detta är en så vanlig situation att Hibernate har lagt till en speciell anteckning som låter dig lagra tidszonen för ett specifikt datum i en separat kolumn.

Exempel:

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

Det här är en krycka. Men det finns också en ursäkt för det: det dök upp vid en tidpunkt då DateTime API ännu inte existerade. Och det var omöjligt att lagra TimeZone i klassen java.util.Date.

Jag hoppas verkligen att du inte kommer att se detta ofta i din kod.

Kommentarer
  • Populär
  • Ny
  • Gammal
Du måste vara inloggad för att lämna en kommentar
Den här sidan har inga kommentarer än