Descripción

En la lección anterior, vio que Hibernate usa una columna DTYPE VARCHAR especial para almacenar el nombre de una clase de Entidad. Tal columna se llama discriminador . Se utiliza para determinar sin ambigüedades qué clase crear para una fila dada en la base de datos.

Puede manipular esta columna con la anotación @DiscriminatorColumn . Ejemplo:

@DiscriminatorColumn(name="column_name",   discriminatorType = DiscriminatorType.INTEGER)

Según la especificación JPA, un discriminador puede tener los siguientes tipos:

  • CADENA
  • CARBONIZARSE
  • ENTERO

Sin embargo, Hibernate le permite expandir un poco esta lista. Admite estos tipos de Java: String, char, int, byte, short, boolean.

Si usamos el tipo INTEGER, ¿cómo codificar el nombre de la clase Entity en él? Para esto, se usa otra anotación: @DiscriminatorValue .

Mira un ejemplo:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
@DiscriminatorValue("1")
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
@DiscriminatorValue("2")
class Client extends User {
   String address;
}

En el ejemplo anterior, le dijimos a Hibernate que el discriminador usará la columna user_type, que almacenará números. Si almacena el valor 1, significa que el tipo de fila es Empleado, si se almacena 2, entonces el tipo de fila es Cliente. Sencillo y hermoso.

@ValorDiscriminador

Pero eso no es todo. Puede decirle a Hibernate cómo interpretar el tipo de una cadena cuando su discriminador es NULL.

En realidad es muy simple. Especifique el valor nulo para la anotación @DiscriminatorValue . Por ejemplo, así:

@DiscriminatorValue("null")

Ejemplo de clase:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("null")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}

Le hemos dicho a Hibernate que cualquier fila de la tabla que tenga NULL en la columna tipo_usuario debe interpretarse como un objeto de tipo Usuario.

Pero eso no es todo. Hay otro valor interesante para la anotación @DiscriminatorValue.

Aquí está esto:

@DiscriminatorValue("not null")

Ejemplo de clase:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("not null")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}

Con esta anotación, le dijimos a Hibernate que cualquier fila de la tabla con un valor que no sea NULO en la columna tipo_usuario debe interpretarse como un objeto de tipo Usuario. Pero esto es solo para el caso si no se encuentra una clase que tenga el número requerido explícitamente especificado.

Así funcionará para diferentes valores de los discriminadores:

  • 0 - crea un objeto de tipo Usuario
  • 1 - crea un objeto de tipo Empleado
  • 2 - crear un objeto de tipo Cliente
  • 3 - crea un objeto de tipo Usuario
  • 4 - crea un objeto de tipo Usuario

@Fórmula Discriminadora

Pero eso no es todo. Para nuestro discriminador, podemos especificar una fórmula entera mediante la cual calculará los valores para la anotación @DiscriminatorValue .

Hay una anotación especial para esto, se llama @DiscriminatorFormula .

Ejemplo:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorFormula("case when ‘join’ is not null then 1 else 2 end")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
@DiscriminatorValue("1")
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
@DiscriminatorValue("2")
class Client extends User {
   String address;
}

Hibernate comparará los valores devueltos por @DiscriminatorFormula con los valores especificados en las anotaciones @DiscriminatorValue . Con él, puedes escribir escenarios bastante complejos:

@DiscriminatorFormula(
           	"case when address is not null " +
           	"then 'Client' " +
           	"else (" +
           	"   case when occupation is not null " +
           	"   then 'Employee' " +
           	"   else 'Unknown' " +
           	"   end) " +
           	"end "
)