Beschrijving

In de vorige les zag je dat Hibernate een speciale DTYPE VARCHAR-kolom gebruikt om de naam van een Entity-klasse op te slaan. Zo'n kolom wordt een discriminator genoemd . Het wordt gebruikt om ondubbelzinnig te bepalen welke klasse moet worden gemaakt voor een bepaalde rij in de database.

U kunt deze kolom manipuleren met de annotatie @DiscriminatorColumn . Voorbeeld:

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

Volgens de JPA-specificatie kan een discriminator de volgende typen hebben:

  • SNAAR
  • CHAR
  • GEHEEL GETAL

Met Hibernate kunt u deze lijst echter een beetje uitbreiden. Het ondersteunt deze Java-typen: String, char, int, byte, short, boolean.

Als we het INTEGER-type gebruiken, hoe coderen we dan de naam van de Entity-klasse erin? Hiervoor wordt een andere annotatie gebruikt - @DiscriminatorValue .

Kijk naar een voorbeeld:

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

In het bovenstaande voorbeeld hebben we Hibernate verteld dat de discriminator de kolom user_type zal gebruiken, waarin nummers worden opgeslagen. Als het de waarde 1 opslaat, betekent dit dat het rijtype Werknemer is, als 2 is opgeslagen, dan is het rijtype Klant. Eenvoudig en mooi.

@DiscriminatorValue

Maar dat is niet alles. U kunt Hibernate vertellen hoe het type string moet worden geïnterpreteerd wanneer de discriminator NULL is.

Het is eigenlijk heel simpel. U geeft de null-waarde op voor de annotatie @DiscriminatorValue . Bijvoorbeeld als volgt:

@DiscriminatorValue("null")

Klasse voorbeeld:

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

We hebben Hibernate verteld dat elke tabelrij met NULL in de kolom user_type moet worden geïnterpreteerd als een object van het type User.

Maar dat is niet alles. Er is nog een interessante waarde voor de annotatie @DiscriminatorValue.

Hier is dit:

@DiscriminatorValue("not null")

Klasse voorbeeld:

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

Met deze annotatie vertelden we Hibernate dat elke tabelrij met een niet-NULL-waarde in de user_type-kolom moet worden geïnterpreteerd als een object van het type User. Maar dit is alleen het geval als er geen klasse wordt gevonden waarvan het vereiste aantal expliciet is opgegeven.

Dit is hoe het zal werken voor verschillende waarden van de discriminatoren:

  • 0 - maak een object van het type Gebruiker
  • 1 - maak een object van het type Medewerker
  • 2 - maak een object van het type Client
  • 3 - maak een object van het type Gebruiker
  • 4 - maak een object van het type Gebruiker

@DiscriminatorFormula

Maar dat is niet alles. Voor onze discriminator kunnen we een integerformule specificeren waarmee de waarden voor de @DiscriminatorValue- annotatie worden berekend .

Hier is een speciale annotatie voor, deze heet @DiscriminatorFormula .

Voorbeeld:

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

De waarden die worden geretourneerd door @DiscriminatorFormula worden door Hibernate vergeleken met de waarden die zijn opgegeven in de @DiscriminatorValue- annotaties . Hiermee kun je behoorlijk complexe scenario's schrijven:

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