Mapeo de enumeraciones con @Enumerated

Tutorial de JPA @EnumeratedUna de las ventajas de utilizar enumeraciones en Java, es podemos limitar los valores posibles para una propiedad, forzando a los desarrolladores a utilizar los valores ya definidos y evitando el margen de error.

@Enumerated

Con JPA tambi茅n es posible utilizar enumeraciones y pueden ser de mucha ayuda para asegurar que los programadores persistan un valor v谩lido dentro de una lista previamente definida. JPA nos permite mediante la anotaci贸n @Enumerated definir la forma en que una enumeraci贸n ser谩 persistida, las cuales se explican a continuaci贸n:

  • String: permite persistir la enumeraci贸n por su nombre, lo que significa que ser谩 una columna alfanum茅rica. La anotaci贸n quedar铆a as铆:
    • @Enumerated(value = EnumType.STRING)
  • Ordinal: esta estrategia persiste un valor entero que corresponde al valor ordinal o posici贸n de valor en la enumeraci贸n. La anotaci贸n quedar铆a de la siguiente manera:
    • @Enumerated(value = EnumType.ORDINAL)

Retomaremos la entidad Employee que hemos venido analizando en todo este tutorial y le agregaremos una nueva propiedad que corresponda al status:

package com.obb.jpa.jpaturorial.entity;

import java.util.Calendar;
import java.util.Objects;
import javax.persistence.*;

/**
 * @author Oscar Blancarte
 */
@Entity
@Table(
    name = "EMPLOYEES" , 
    schema = "jpatutorial", 
    indexes = {@Index(name = "name_index", columnList = "name",unique = true)}
)
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "EmployeeTable")
    @Column(name = "ID")
    private Long id;
    
    @Column(name = "NAME", nullable = false, length = 150)
    private String name; 
    
    @Column(name = "SALARY", nullable = false, scale = 2)
    private double salary;
    
    @Column(name = "REGIST_DATE", updatable = false, nullable = false)
    @Temporal(TemporalType.DATE)
    private Calendar registDate;
    
    @Column(name="status", nullable = false, length = 8 )
    @Enumerated(value = EnumType.STRING)
    private Status status;
    
    /**
     * GETs and SETs
     */
}

Veamos que la propiedad es de tipo Status, la cual es una enumeraci贸n y tiene definida la estrategia String. Tambi茅n podemos ver que est谩 definida la anotaci贸n @Column para definir las caracter铆sticas de la columna.

Por otra parte, tenemos la enumeraci贸n Status la cual tiene los posibles valores ACTIVE e INACTIVE.

package com.obb.jpa.jpaturorial.entity;

/**
 * @author Oscar Blancarte
 */
public enum Status {
    ACTIVE,
    INACTIVE
}

La anotaci贸n @Enumerated no es mandataria, pero el hecho de omitirla provocara que JPA determine la estrategia por default, que en nuestro caso ser铆a Ordinal. Por eso yo siempre aconsejo definirla para no tener sorpresas.

Si ejecutamos nuestro el programa para que cree las tablas por nosotros veremos que se creara una columna de tipo VARCHAR ya que definimos String como estrategia. Por otro lado, si utilizamos Ordinal se crear谩 una columna de tipo INT.

Tamb铆en los quiero invitar a ver mi curso de JPA, donde explico todos estos temas aplicados con API REST,聽https://codmind.com/courses/jpa

馃憠馃憠聽Los invito a mi聽Curso de Mastering JPA, donde habla de todos estos temas y crearemos un API REST para probar todos los conceptos de persistencia.
馃憟馃憟

Yo siempre recomiendo utilizar Enumeraciones cuando definamos atributos que requieren valores fijos y previamente determinados, como una lista de valores, pero que esta lista no requiera cambiar en tiempo de ejecuci贸n. Una mala opci贸n para utilizarla es para definir listas de valores que en el futuro requieran ampliarse sin necesidad de recompilar.

NOTA: Este art铆culo es solo una secci贸n del Tutorial de JPA, para ver el contenido completo de este tutorial regresa al 脥ndice en el bot贸n de abajo.

Anterior脥ndiceSiguiente

2 thoughts to “Mapeo de enumeraciones con @Enumerated”

  1. Que pasa si quiere almacenarlo en la BD con un valor que no es el nombre ni el ordinal. Por ejemplo:

    public enum EstadoVerificacion {
    NO_VERIFICADO( 10, “No verificado” ),
    VERIFICADO( 20, “Ya se verifico” ),
    DOCUMENTO_GENERADO( 35, “Documento generado” );

    private final int id;
    private final String description;

    private EstadoVerificacion( int id, String description ) {
    this.id = id;
    this.description = description;
    }

    public int getId() {
    return id;
    }

    public String getDescription() {
    return description;
    }
    }

    Quiero que sea el campo id quien se almacene en la BD.

    Otra pregunta, utilizar el Ordinal 驴no es muy riesgoso? es decir otro programador (en un entorno compartido) puede querer agregar un nuevo estado y no necesariamente meterlo al final, el enum lo permite. Puede que haya un pacto de caballeros de nunca cambiar el orden y agregarlo al final, pero dado que no es una restricci贸n de java, cualquiera puede no conocerla y agregarlo donde mejor le plazca, afectando entonces el n煤mero que se ven铆a almacenando en la BD. Yo por eso raz贸n (y quiero saber si hay una mejor pr谩ctica) mejor los hago como el ejemplo que pas茅 y as铆 obligo a que sea ese id y ning煤n otro, lo malo es que no puedo poner en los entities la enumeraci贸n sino tengo que poner un int o long, quit谩ndole elegancia al m茅todo, que se viera mucho mejor si se restringe al enum.

    Gracias por su aclaraci贸n.

    1. Hola Rober, JPA solo soporta guardar las enumeraciones por el NAME o por el ORDINAL, el ordinal guarda la posici贸n en que se encuentra la enumeraci贸n y el NAME guarda el nombre exacto de la enumeraci贸n, por lo que que comentas no es posible.
      Con respecto a lo del ordinal, es correcto guardar el ordinal es un riesgo muy grande, incluso yo nunca guardo la enumeraci贸n por el ordinal, por lo mismo que mencionas.

Deja un comentario

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *