Descriere

În lecția anterioară, ați văzut că Hibernate folosește o coloană specială DTYPE VARCHAR pentru a stoca numele unei clase de Entitate. O astfel de coloană se numește discriminator . Este folosit pentru a determina fără ambiguitate ce clasă să creeze pentru un anumit rând din baza de date.

Puteți manipula această coloană cu adnotarea @DiscriminatorColumn . Exemplu:

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

Conform specificației JPA, un discriminator poate avea următoarele tipuri:

  • ŞIR
  • CHAR
  • ÎNTREG

Cu toate acestea, Hibernate vă permite să extindeți puțin această listă. Acceptă aceste tipuri de Java: String, char, int, byte, short, boolean.

Dacă folosim tipul INTEGER, atunci cum să codificăm numele clasei Entity în el? Pentru aceasta, se folosește o altă adnotare - @DiscriminatorValue .

Uită-te la un exemplu:

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

În exemplul de mai sus, i-am spus lui Hibernate că discriminatorul va folosi coloana user_type, care va stoca numere. Dacă stochează valoarea 1, înseamnă că tipul de rând este Angajat, dacă este stocat 2, atunci tipul de rând este Client. Simplu și frumos.

@DiscriminatorValue

Dar asta nu este tot. Puteți spune lui Hibernate cum să interpreteze tipul unui șir atunci când discriminatorul său este NULL.

De fapt, este foarte simplu. Specificați valoarea nulă pentru adnotarea @DiscriminatorValue . De exemplu, așa:

@DiscriminatorValue("null")

Exemplu de clasă:

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

I-am spus lui Hibernate că orice rând de tabel care are NULL în coloana user_type ar trebui interpretat ca un obiect de tip User.

Dar asta nu este tot. Există o altă valoare interesantă pentru adnotarea @DiscriminatorValue.

Iată asta:

@DiscriminatorValue("not null")

Exemplu de clasă:

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

Cu această adnotare, i-am spus lui Hibernate că orice rând de tabel cu o valoare non-NULL în coloana user_type ar trebui interpretat ca un obiect de tip User. Dar acest lucru este valabil doar în cazul în care nu este găsită o clasă care are numărul necesar specificat în mod explicit.

Iată cum va funcționa pentru diferite valori ale discriminatorilor:

  • 0 - creați un obiect de tip User
  • 1 - creați un obiect de tip Employee
  • 2 - creați un obiect de tip Client
  • 3 - creați un obiect de tip User
  • 4 - creați un obiect de tip User

@DiscriminatorFormula

Dar asta nu este tot. Pentru discriminatorul nostru, putem specifica o formulă întreagă prin care va calcula valorile pentru adnotarea @DiscriminatorValue .

Există o adnotare specială pentru aceasta, se numește @DiscriminatorFormula .

Exemplu:

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

Valorile returnate de @DiscriminatorFormula vor fi comparate de Hibernate cu valorile specificate în adnotările @DiscriminatorValue . Cu el, puteți scrie scenarii destul de complexe:

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