Liste des collections

Eh bien, vous avez vu comment mapper des types simples. Il est maintenant temps de passer à des questions plus intéressantes - comment cartographier des collections d'objets.

Et nous pouvons avoir des objets en 5 groupes :

  • Array - un tableau d'objets
  • Liste - liste d'objets
  • Ensemble - ensemble d'objets
  • Carte - un dictionnaire d'objets
  • Collection - une collection d'objets

Et un exemple de classe avec un champ collection :

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @magical-annotation
   public List messages;
}

Quelle est donc cette annotation magique qui va nous permettre de stocker non pas un champ, mais plusieurs valeurs ?

Cette annotation s'appelle @ElementCollection . Exemple:

@Entity
@Table(name="user")
class User  {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   public List<String> messages;
}

Il est écrit très simplement, mais il fonctionne de manière non triviale.

Table auxiliaire

Tous les champs de la classe Entity qui contiennent de nombreux éléments et sont marqués avec l' annotation @ElementCollection sont contenus dans la base de données dans une table auxiliaire spéciale. Ce qui, en fait, est logique.

Cette table peut contenir des données sous deux formes :

  • Ordered (List, Map) contient trois colonnes :
    • Colonne clé (clé étrangère) - référence à l'ID de l'objet parent.
    • Colonne d'index - position/index dans la collection.
    • Colonne d'élément - valeur.
  • Unordered (Set) contient deux colonnes :
    • Colonne clé (clé étrangère) - référence à l'ID de l'objet parent.
    • Colonne d'élément - valeur.

Vous pouvez également définir explicitement le nom de cette table à l'aide d'une annotation :

@CollectionTable(name="table_name")

Exemple:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message")
   public List<String> messages;
}

Important! Si l' annotation @CollectionTable n'est pas spécifiée, alors Hibernate construira le nom de la table elle-même en se basant sur le nom de la classe et le nom du champ : la classe User et le champmessagesnommez la table "User_messages".

Collecte Collecte

Mais ne laissons pas la création de la table auxiliaire à Hibernate et créons-la nous-mêmes. Nous devons d'abord créer un tableau à deux colonnes :

CREATE TABLE user_message {
    user_id INT,
    message VARCHAR(255)
};

Notez que cette table n'a pas sa propre colonne id. C'est la caractéristique principale des tables auxiliaires. Vous vous familiariserez un peu plus tard avec d'autres types de tables auxiliaires.

Maintenant, nous devons mapper cette table sur notre champmessagesdans la classe Utilisateur . Cela ressemblera à ceci :

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message", joinColumns = @JoinColumn(name = "user_id"))
   @Column(name = "message")
   public Set<String> messages;
}

Ici, il convient de prêter attention à deux choses.

Tout d'abord, la colonne de message, spécifiée avec l' annotation @Column(name = "message") , se trouve dans la table auxiliaire user_message, pas dans la table user.

Deuxièmement, dans l' annotation @JoinColumn(name = "user_id") , nous avons spécifié le nom de la colonne user_id, qui fait référence à l'identifiant de la table utilisateur. C'est pour qu'Hibernate sache comment les combiner correctement.

Collection

Si vous souhaitez stocker les éléments ordonnés d'une liste ou d'un tableau dans une table auxiliaire, vous avez besoin d'une table à trois colonnes :

CREATE TABLE user_message {
    user_id INT,
    index INT,
    message VARCHAR(255)
};

Si vous n'aimez pas le nom de colonne « index » ou si vous ne pouvez pas le modifier, vous pouvez spécifier un nom différent lors du mappage. Pour ce faire, vous devez utiliser l' annotation @Index .

Exemple:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message",
       	indexes = { @Index(columnList = "list_index") }
       	joinColumns = @JoinColumn(name = "user_id"))
   @Column(name = "message")
   public List<String> messages;
}

Collecte de cartes

Et enfin, vous voulez stocker non seulement une collection, mais un HashMap, et vous avez besoin de deux colonnes dans une table auxiliaire pour cela :

CREATE TABLE user_message {
    user_id INT,
    key VARCHAR(255),
    message VARCHAR(255)
};

Afin de spécifier une clé pour une carte, vous avez besoin de l' annotation @MapKeyColumn .

Exemple:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message", joinColumns = @JoinColumn(name = "user_id"))
   @MapKeyColumn(name = "key")
   @Column(name = "message")
   public Map<String, String> messages;
}

Vous pouvez trouver plus d'informations dans la documentation officielle .