Mappage des dates

Disponible

4.1 Excursus dans l'histoire

La tâche d'enregistrement des objets Java dans la base de données était pertinente presque immédiatement après la création du langage Java. À cette époque, il n'y avait qu'un seul type de données dans le langage Java, Date, qui stockait l'heure selon la norme UNIX : en nombre de millisecondes depuis 1970.

Eh bien, dans les bases de données à cette époque, il y avait déjà différents types de données pour les dates, du moins il y avait des types distincts pour la date, l'heure et la date + heure :

  • DATE
  • TEMPS
  • HORODATAGE

Par conséquent, les créateurs du langage Java y ont ajouté un package spécial - java.sql, qui contenait des classes :

  • java.sql.date
  • java.sql.Heure
  • java.sql.horodatage

Cartographier ces classes est un vrai plaisir :

@Entity
public class TemporalValues {

	@Basic
    private java.sql.Date sqlDate;

	@Basic
    private java.sql.Time sqlTime;

    @Basic
    private java.sql.Timestamp sqlTimestamp;
}

Mais comme les programmeurs travaillaient avec la classe java.util.Date, Hibernate a ajouté une annotation spéciale @Temporalafin de contrôler le mappage du type Date.

Exemple:

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

Le type java.util.Calendaret java.util.Datele type par défaut utilisent le type TIMESTAMP pour les représenter dans la base de données.

4.2 Nouvelle heure

Actuellement, avec la cartographie, tout est beaucoup plus simple et meilleur. Toutes les bases de données prennent en charge 4 types de données pour travailler avec le temps :

  • DATE - date : année, mois et jour.
  • TIME - temps : heures, minutes, secondes.
  • TIMESTAMP - date, heure et nanosecondes.
  • HORODATAGE AVEC FUSEAU HORAIRE - HORODATAGE et fuseau horaire (nom de zone ou décalage).

Pour représenter le type DATEen Java, vous devez utiliser une classe java.time.LocalDatede l'API DateTime JDK 8.

TaperTEMPSde la base de données peut être représenté par deux types de Java : java.time.LocalTimeet java.time.OffsetTime. Rien de compliqué.

Et la date et l'heure exactes représentées par le typeHORODATAGEdans la base, en Java il peut être représenté par 4 types :

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

et enfinHORODATAGE AVEC FUSEAU HORAIREpeut être représenté par deux types :

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

Puisque vous êtes déjà familiarisé avec l'API DateTime , vous souvenir de ce sujet ne vous sera pas difficile :)

Les cartographier est un pur plaisir :

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

L'annotation @Basicsignifie que le champ doit être traité automatiquement : Hibernate décidera sur quelle colonne et quel type ce champ doit être mappé.

4.3 Travailler avec les fuseaux horaires

Si le fuseau horaire fait partie d'une date, alors les stocker dans la base de données est simple - tout comme une date normale :

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;

Toutefois, si vous souhaitez stocker les fuseaux horaires séparément de la date :

@Basic
private java.time.TimeZone timeZone;

@Basic
private java.time.ZoneOffset zonedOffset;

Ensuite, Hibernate les stockera par défaut dans le type VARCHAR. Ce qui, en fait, est logique, puisque le TimeZone a généralement un nom de chaîne comme "UTC + 3" ou "Cairo".

4.4 Définir votre propre fuseau horaire

Lorsque vous travaillez avec des dates d'enregistrement dans la base de données, vous constaterez qu'il existe déjà 4 endroits où vous pouvez définir le fuseau horaire actuel :

  • système d'exploitation du serveur ;
  • SGBD ;
  • Application Java
  • Hiberner.

Si le SGBD ne spécifie pas de fuseau horaire (TimeZone), il le prendra dans les paramètres du système d'exploitation. Cela peut être gênant, car les SGBD de sauvegarde sont souvent situés dans d'autres centres de données qui ont leur propre fuseau horaire.

Par conséquent, presque tous les administrateurs de SGBD définissent une zone unique afin que les données puissent être facilement transférées d'un serveur à un autre.

La situation est similaire avec une application Java. Il peut également être exécuté sur différents serveurs dans différents centres de données, il a donc généralement un fuseau horaire explicite.

java -Duser.timezone=UTC ...

Ou pendant que le programme est en cours d'exécution :

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

Et, bien sûr, Hibernate vous permet de définir explicitement votre fuseau horaire.

Tout d'abord, il peut être spécifié lors de la configuration de la SessionFactory :

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

Deuxièmement, le fuseau horaire peut être spécifiépour une session spécifique:

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

4.5 Annotation @TimeZoneStorage

Il arrive souvent que les programmeurs commencent à concevoir une base de données basée sur le travail dans un pays (et un fuseau horaire), puis après quelques années, ils doivent ajouter la prise en charge du travail dans différents fuseaux horaires.

Par conséquent, ils ont simplement ajouté une colonne distincte à la base de données pour stocker le fuseau horaire. C'est une situation si courante qu'Hibernate a ajouté une annotation spéciale qui vous permet de stocker le fuseau horaire d'une date spécifique dans une colonne séparée.

Exemple:

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

C'est une béquille. Mais il y a aussi une excuse à cela : il est apparu à une époque où l'API DateTime n'existait pas encore. Et il était impossible de stocker TimeZone dans la classe java.util.Date.

J'espère vraiment que vous ne verrez pas souvent cela dans votre code.

Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires