Описание
В предыдущей лекции ты видел, что Hibernate использует специальную колонку DTYPE VARCHAR для хранения имени Entity-класса. Такая колонка называется дискриминатор. Ее используют для того, чтобы однозначно определить какой класс нужно создать для данной строки базы данных.
Ты можешь управлять этой колонкой с помощью аннотации @DiscriminatorColumn. Пример:
@DiscriminatorColumn(name="имя_колонки", discriminatorType = DiscriminatorType.INTEGER)
Согласно спецификации JPA дискриминатор может иметь такие типы:
- STRING
- CHAR
- INTEGER
Однако Hibernate позволяет немного расширить этот список. Он поддерживает такие Java-типы: String, char, int, byte, short, boolean.
Если мы используем тип INTEGER, то как в нем кодировать имя 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, то это значит, что тип строки – Employee, если хранится 2, то тип строки – Client. Просто и красиво.
@DiscriminatorValue
Но и это еще не все. Ты можешь указать Hibernate, как интерпретировать тип строки, когда ее дискриминатор равен NULL.
На самом деле это очень просто. Ты указываешь значение 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, что любая строка таблицы, где в колонке user_type стоит NULL, должна быть интерпретирована как объект типа 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, что любая строка таблицы, где в колонке user_type стоит значение не NULL, должна быть интерпретирована как объект типа User. Но это только для случая, если не будет найден класс, у которого явно указан нужный номер.
Так работать это будет для разных значений дискриминаторов:
- 0 – создаем объект типа User
- 1 – создаем объект типа Employee
- 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 "
)
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ