Descrição
Na lição anterior, você viu que o Hibernate usa uma coluna especial DTYPE VARCHAR para armazenar o nome de uma classe Entity. Essa coluna é chamada de discriminador . Ele é usado para determinar sem ambiguidade qual classe criar para uma determinada linha no banco de dados.
Você pode manipular esta coluna com a anotação @DiscriminatorColumn . Exemplo:
@DiscriminatorColumn(name="column_name", discriminatorType = DiscriminatorType.INTEGER)
De acordo com a especificação JPA, um discriminador pode ter os seguintes tipos:
- CORDA
- CARACTERES
- INTEIRO
No entanto, o Hibernate permite que você expanda um pouco essa lista. Ele suporta estes tipos Java: String, char, int, byte, short, boolean.
Se usarmos o tipo INTEGER, como codificar o nome da classe Entity nele? Para isso, outra anotação é utilizada - @DiscriminatorValue .
Veja um exemplo:
@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;
}
No exemplo acima, dissemos ao Hibernate que o discriminador usará a coluna user_type, que armazenará números. Se armazenar o valor 1, significa que o tipo de linha é Funcionário, se 2 for armazenado, o tipo de linha é Cliente. Simples e bonito.
@DiscriminatorValue
Mas isso não é tudo. Você pode dizer ao Hibernate como interpretar o tipo de uma string quando seu discriminador é NULL.
Na verdade, é muito simples. Você especifica o valor nulo para a anotação @DiscriminatorValue . Por exemplo, assim:
@DiscriminatorValue("null")
Exemplo de classe:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
Dissemos ao Hibernate que qualquer linha da tabela que tenha NULL na coluna user_type deve ser interpretada como um objeto do tipo User.
Mas isso não é tudo. Há outro valor interessante para a anotação @DiscriminatorValue.
Aqui está isto:
@DiscriminatorValue("not null")
Exemplo de classe:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("not null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
Com esta anotação, dissemos ao Hibernate que qualquer linha da tabela com um valor não NULL na coluna user_type deve ser interpretada como um objeto do tipo User. Mas isso é apenas para o caso de não ser encontrada uma classe que tenha o número necessário explicitamente especificado.
É assim que vai funcionar para diferentes valores dos discriminadores:
- 0 - cria um objeto do tipo User
- 1 - crie um objeto do tipo Funcionário
- 2 - crie um objeto do tipo Cliente
- 3 - crie um objeto do tipo User
- 4 - crie um objeto do tipo User
@DiscriminatorFormula
Mas isso não é tudo. Para nosso discriminador, podemos especificar uma fórmula inteira pela qual ele calculará os valores para a anotação @DiscriminatorValue .
Existe uma anotação especial para isso, ela se chama @DiscriminatorFormula .
Exemplo:
@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;
}
Os valores retornados por @DiscriminatorFormula serão comparados pelo Hibernate com os valores especificados nas anotações @DiscriminatorValue . Com ele, você pode escrever cenários bastante complexos:
@DiscriminatorFormula(
"case when address is not null " +
"then 'Client' " +
"else (" +
" case when occupation is not null " +
" then 'Employee' " +
" else 'Unknown' " +
" end) " +
"end "
)
GO TO FULL VERSION