Enumeración Mapim

Ya hemos descubierto cómo mapear tipos de datos primitivos: usamos la anotación @Column y la anotación @Type . Pero no todos los casos pueden ser cubiertos por estas anotaciones. Y el caso más común es enum .

Los objetos de enumeración de Java se pueden almacenar en la base de datos de dos maneras:

  • como un número
  • como una cadena

Escribamos un pequeño ejemplo en el que el usuario tendrá un color favorito, que se establece mediante enum.


enum Color {
   RED,
   ORANGE,
   YELLOW,
   GREEN,
   BLUE,
   VIOLET
}

Y agregue un campo de color a la clase de usuario :


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

Si queremos que Hibernate guarde el tipo de color en la base como números , entonces necesitamos el campocolor favoritoañadir anotación:


@Enumerated(EnumType.ORDINAL)

Si queremos que los valores se almacenen como cadenas , debemos agregar una anotación:


@Enumerated(EnumType.STRING)

Ejemplo:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Enumerated(EnumType.ORDINAL) //value will be saved to the base as a number
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

Mapim booleano

El segundo escenario útil es el mapeo de tipo booleano. Históricamente sucedió que SQL no tiene su propio tipo de datos para Boolean y en su lugar se usa cualquier cosa.

Las tres opciones más comunes son:

  • 1 o 0
  • 'F' o 'T'
  • 'S' o 'N'

En general, si va a diseñar su base, es mejor escribir el tipo BIT de inmediato. Bueno, el mapeo completo se verá así:


	@Column(name = "is_correct", columnDefinition = "BIT")
	@Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isCorrect;

Bueno, si no está diseñando la base de datos, consulte la tabla anterior y piense en cómo asignar correctamente los tipos que necesita.

Campos calculados

A veces, la cantidad de campos en una clase de Entidad y la cantidad de columnas en una tabla no coinciden. Puede haber varias razones para esto.

Lo más común es cuando hay algún campo en nuestra clase Entity que no queremos guardar en la base de datos. Todo está claro con esto: simplemente agregue la anotación @Transient a dicho campo e Hibernate lo ignorará cuando trabaje con la base de datos.

Ejemplo:


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Transient
           	public Integer total;
}

Esta es una buena opción, pero al leer un objeto de la base de datos, el campo total será nulo. Y nos gustaría que contuviera el producto de ancho*alto. Esto también se puede hacer en Hibernate. Hay una anotación @Formula especial para esto .


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Formula(value = " width * height ")
          	public Integer total;
}

Dicho campo no se guardará en la base de datos, y cuando el objeto se lea de la base de datos, se escribirá en él el valor calculado por la fórmula.

La consulta SQL se verá así:

 SELECT id, width, height, (width* height) AS total FROM Square;

@Incorporado

Otra anotación útil es @Embedded . Le permite considerar los campos del objeto secundario como campos de la propia clase Entidad.

Digamos que tiene una clase de usuario y decide agregarle una dirección:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
    public Integer id;
 
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
 
   @Column(name="created_date")
    public Date createdDate;
}

Todo parece estar bien, pero desde el punto de vista de Java, sería lógico poner la dirección en una clase separada. La dirección sigue siendo una entidad separada. Pero, ¿cómo hacer esto si toda esta información está almacenada en la base de datos en la tabla de usuarios?

La anotación @Embedded nos ayudará . Primero, crearemos la clase UserAddress y pondremos toda la información sobre la dirección del usuario en ella:


@Embeddable
class UserAddress
{
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
}

Y luego usamos un campo de esta clase en nuestra clase Usuario :


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

Gracias a la anotación @Embedded , al momento de guardar el objeto, Hibernate entenderá que los campos de la clase UserAddress necesitan ser tratados como campos de la propia clase User .

¡Importante! Si decide agregar dos campos UserAddress a su clase User , entonces usar @Embedded ya no funcionará: tendrá campos duplicados y deberá separarlos de alguna manera. Esto se hace anulando las anotaciones: usando la anotación @AttributeOverrides .

Quiero que sepas esto, pero no entraremos en detalles aquí. Creo que esto es suficiente para que te rompas la cabeza. Para los curiosos, puedo dejar un enlace a la documentación oficial .