Lista de colecciones

Bueno, has visto cómo mapear tipos simples. Ahora es el momento de pasar a preguntas más interesantes: cómo mapear colecciones de objetos.

Y podemos tener objetos en 5 grupos:

  • Matriz - una matriz de objetos
  • Lista - lista de objetos
  • Conjunto - conjunto de objetos
  • Mapa - un diccionario de objetos
  • Colección - una colección de objetos

Y un ejemplo de una clase con un campo de colección:

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

   @magical-annotation
   public List messages;
}

Entonces, ¿qué es esta anotación mágica que nos permitirá almacenar no un campo, sino muchos valores?

Esta anotación se llama @ElementCollection . Ejemplo:

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

   @ElementCollection
   public List<String> messages;
}

Está escrito de manera muy simple, pero funciona de manera no trivial.

Mesa auxiliar

Todos los campos de la clase Entity que contienen muchos elementos y están marcados con la anotación @ElementCollection están contenidos en la base de datos en una tabla auxiliar especial. Lo cual, de hecho, es lógico.

Esta tabla puede contener datos en dos formas:

  • Ordenado (Lista, Mapa) contiene tres columnas:
    • Columna clave (clave externa): referencia al ID del objeto principal.
    • Columna de índice : posición/índice en la colección.
    • Columna de elemento - valor.
  • Unordered (Set) contiene dos columnas:
    • Columna clave (clave externa): referencia al ID del objeto principal.
    • Columna de elemento - valor.

También puede establecer el nombre de esta tabla de forma explícita mediante una anotación:

@CollectionTable(name="table_name")

Ejemplo:

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

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

¡Importante! Si no se especifica la anotación @CollectionTable , Hibernate creará el nombre de la tabla basándose en el nombre de la clase y el nombre del campo: la clase de Usuario y el campomensajesnombra la tabla "User_messages".

Colección Colección

Pero no dejemos la creación de la tabla auxiliar a Hibernate y la creemos nosotros. Primero necesitamos crear una tabla con dos columnas:

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

Tenga en cuenta que esta tabla no tiene su propia columna de identificación. Esta es la característica principal de las mesas auxiliares. Te familiarizarás con otros tipos de mesas auxiliares un poco más adelante.

Ahora necesitamos mapear esta tabla a nuestro campo.mensajesen la clase Usuario . Esto se verá así:

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

Aquí vale la pena prestar atención a dos cosas.

Primero, la columna del mensaje, especificada con la anotación @Column(name = "message") , está en la tabla auxiliar user_message, no en la tabla de usuarios.

En segundo lugar, en la anotación @JoinColumn(name = "user_id") , especificamos el nombre de la columna user_id, que hace referencia al id de la tabla de usuarios. Esto es para que Hibernate sepa cómo combinarlos correctamente.

Recopilación

Si desea almacenar los elementos ordenados de una lista o matriz en una tabla auxiliar, necesita una tabla con tres columnas:

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

Si no le gusta el nombre de columna "índice" o no puede cambiarlo, puede especificar un nombre diferente durante la asignación. Para hacer esto, necesita usar la anotación @Index .

Ejemplo:

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

Colección de mapas

Y, por último, desea almacenar no solo una colección, sino también un HashMap, y necesita dos columnas en una tabla auxiliar para ello:

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

Para especificar una clave para un mapa, necesita la anotación @MapKeyColumn .

Ejemplo:

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

Puedes encontrar más información en la documentación oficial .