Opis

W poprzedniej lekcji widziałeś, że Hibernate używa specjalnej kolumny DTYPE VARCHAR do przechowywania nazwy klasy Entity. Taka kolumna nazywana jest dyskryminatorem . Służy do jednoznacznego określenia, jaką klasę utworzyć dla danego wiersza w bazie danych.

Możesz manipulować tą kolumną za pomocą adnotacji @DiscriminatorColumn . Przykład:

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

Zgodnie ze specyfikacją JPA dyskryminator może mieć następujące typy:

  • STRUNOWY
  • ZWĘGLAĆ
  • LICZBA CAŁKOWITA

Jednak Hibernate pozwala nieco rozszerzyć tę listę. Obsługuje następujące typy Java: String, char, int, byte, short, boolean.

Jeśli używamy typu INTEGER, to jak zakodować w nim nazwę klasy Entity? W tym celu używana jest inna adnotacja - @DiscriminatorValue .

Spójrz na przykład:

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

W powyższym przykładzie powiedzieliśmy Hibernate, że dyskryminator użyje kolumny typ_użytkownika, w której będą przechowywane liczby. Jeśli przechowuje wartość 1, oznacza to, że typem wiersza jest Pracownik, jeśli przechowywana jest wartość 2, wówczas typem wiersza jest Klient. Proste i piękne.

@DiscriminatorValue

Ale to nie wszystko. Możesz powiedzieć Hibernate, jak interpretować typ łańcucha, gdy jego wyróżnikiem jest NULL.

Właściwie to bardzo proste. Określasz wartość null dla adnotacji @DiscriminatorValue . Na przykład tak:

@DiscriminatorValue("null")

Przykład klasy:

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

Powiedzieliśmy Hibernate, że każdy wiersz tabeli, który ma wartość NULL w kolumnie typ_użytkownika, powinien być interpretowany jako obiekt typu Użytkownik.

Ale to nie wszystko. Istnieje jeszcze jedna interesująca wartość adnotacji @DiscriminatorValue.

Oto to:

@DiscriminatorValue("not null")

Przykład klasy:

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

Dzięki tej adnotacji powiedzieliśmy Hibernate, że każdy wiersz tabeli z wartością różną od NULL w kolumnie user_type powinien być interpretowany jako obiekt typu User. Ale dotyczy to tylko przypadku, gdy nie zostanie znaleziona klasa, która ma wyraźnie określony wymagany numer.

Tak to będzie działać dla różnych wartości dyskryminatorów:

  • 0 - utwórz obiekt typu Użytkownik
  • 1 - utwórz obiekt typu Pracownik
  • 2 - utwórz obiekt typu Klient
  • 3 - utwórz obiekt typu Użytkownik
  • 4 - utwórz obiekt typu Użytkownik

@DiscriminatorFormula

Ale to nie wszystko. Dla naszego dyskryminatora możemy podać formułę całkowitą, według której obliczy on wartości dla adnotacji @DiscriminatorValue .

Jest do tego specjalna adnotacja, nazywa się @DiscriminatorFormula .

Przykład:

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

Wartości zwrócone przez @DiscriminatorFormula zostaną porównane przez Hibernate z wartościami określonymi w adnotacjach @DiscriminatorValue . Dzięki niemu możesz pisać dość złożone scenariusze:

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