Описание
В предишния урок видяхте, че 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 "
)