Description

Dans la leçon précédente, vous avez vu qu'Hibernate utilise une colonne spéciale DTYPE VARCHAR pour stocker le nom d'une classe Entity. Une telle colonne s'appelle un discriminateur . Il est utilisé pour déterminer sans ambiguïté quelle classe créer pour une ligne donnée dans la base de données.

Vous pouvez manipuler cette colonne avec l' annotation @DiscriminatorColumn . Exemple:

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

Selon la spécification JPA, un discriminateur peut avoir les types suivants :

  • CHAÎNE
  • CARBONISER
  • ENTIER

Cependant, Hibernate vous permet d'étendre un peu cette liste. Il prend en charge ces types Java : String, char, int, byte, short, boolean.

Si nous utilisons le type INTEGER, alors comment y coder le nom de la classe Entity ? Pour cela, une autre annotation est utilisée - @DiscriminatorValue .

Regardez un exemple :

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

Dans l'exemple ci-dessus, nous avons indiqué à Hibernate que le discriminateur utilisera la colonne user_type, qui stockera les nombres. S'il stocke la valeur 1, cela signifie que le type de ligne est Employé, si 2 est stocké, alors le type de ligne est Client. Simple et beau.

@DiscriminatorValue

Mais ce n'est pas tout. Vous pouvez indiquer à Hibernate comment interpréter le type d'une chaîne lorsque son discriminateur est NULL.

C'est en fait très simple. Vous spécifiez la valeur nulle pour l' annotation @DiscriminatorValue . Par exemple, comme ceci :

@DiscriminatorValue("null")

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

Nous avons dit à Hibernate que toute ligne de table qui a NULL dans la colonne user_type doit être interprétée comme un objet de type User.

Mais ce n'est pas tout. Il existe une autre valeur intéressante pour l'annotation @DiscriminatorValue.

Voici ceci :

@DiscriminatorValue("not null")

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

Avec cette annotation, nous avons indiqué à Hibernate que toute ligne de table avec une valeur non NULL dans la colonne user_type doit être interprétée comme un objet de type User. Mais ce n'est que pour le cas où une classe n'est pas trouvée qui a le nombre requis explicitement spécifié.

Voici comment cela fonctionnera pour différentes valeurs des discriminateurs :

  • 0 - crée un objet de type Utilisateur
  • 1 - créer un objet de type Employé
  • 2 - créer un objet de type Client
  • 3 - créer un objet de type Utilisateur
  • 4 - créer un objet de type Utilisateur

@DiscriminatorFormula

Mais ce n'est pas tout. Pour notre discriminateur, nous pouvons spécifier une formule entière par laquelle il calculera les valeurs de l' annotation @DiscriminatorValue .

Il existe une annotation spéciale pour cela, elle s'appelle @DiscriminatorFormula .

Exemple:

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

Les valeurs renvoyées par @DiscriminatorFormula seront comparées par Hibernate avec les valeurs spécifiées dans les annotations @DiscriminatorValue . Avec lui, vous pouvez écrire des scénarios assez complexes :

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