Описание

В предишния урок видяхте, че Hibernate използва специална колона DTYPE VARCHAR за съхраняване на името на клас Entity. Такава колона се нарича дискриминатор . Използва се за недвусмислено определяне кой клас да се създаде за даден ред в базата данни.

Можете да манипулирате тази колона с анотацията @DiscriminatorColumn . Пример:

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

Според спецификацията на JPA дискриминаторът може да има следните типове:

  • STRING
  • CHAR
  • ЦЯЛО ЧИСЛО

Hibernate обаче ви позволява да разширите малко този списък. Поддържа следните типове Java: String, char, int, byte, short, boolean.

Ако използваме типа INTEGER, тогава How да codeираме името на класа Entity в него? За целта се използва друга анотация - @DiscriminatorValue .

Вижте пример:

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

В горния пример казахме на Hibernate, че дискриминаторът ще използва колоната user_type, която ще съхранява числа. Ако съхранява стойност 1, това означава, че типът на реда е Служител, ако се съхранява 2, тогава типът на реда е Клиент. Просто и красиво.

@DiscriminatorValue

Но това не е всичко. Можете да кажете на Hibernate How да интерпретира типа на низ, когато неговият дискриминатор е NULL.

Всъщност е много просто. Посочвате нулевата стойност за анотацията @DiscriminatorValue . Например така:

@DiscriminatorValue("null")

Пример за клас:

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

Казахме на Hibernate, че всеки ред от table, който има NULL в колоната user_type, трябва да се интерпретира като обект от тип User.

Но това не е всичко. Има още една интересна стойност за анотацията @DiscriminatorValue.

Ето това:

@DiscriminatorValue("not null")

Пример за клас:

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

С тази анотация казахме на Hibernate, че всеки ред на table с различна от NULL стойност в колоната user_type трябва да се интерпретира като обект от тип User. Но това е само в случай, че не е намерен клас, който има изрично посочен необходимия номер.

Ето How ще работи за различни стойности на дискриминаторите:

  • 0 - създаване на обект от тип User
  • 1 - създаване на обект от тип Служител
  • 2 - създаване на обект от тип Client
  • 3 - създаване на обект от тип User
  • 4 - създаване на обект от тип User

@DiscriminatorFormula

Но това не е всичко. За нашия дискриминатор можем да посочим целочислена формула, чрез която ще изчисли стойностите за анотацията @DiscriminatorValue .

Има специална анотация за това, тя се нарича @DiscriminatorFormula .

Пример:

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

Стойностите, върнати от @DiscriminatorFormula, ще бъдат сравнени от Hibernate със стойностите, посочени в анотациите @DiscriminatorValue . С него можете да пишете доста сложни сценарии:

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