Description
In the previous lesson, you saw that Hibernate uses a special DTYPE VARCHAR column to store the name of an Entity class. Such a column is called a discriminator . It is used to unambiguously determine which class to create for a given row in the database.
You can manipulate this column with the @DiscriminatorColumn annotation . Example:
@DiscriminatorColumn(name="column_name", discriminatorType = DiscriminatorType.INTEGER)
According to the JPA specification, a discriminator can have the following types:
- STRING
- CHAR
- INTEGER
However, Hibernate allows you to expand this list a bit. It supports these Java types: String, char, int, byte, short, boolean.
If we use the INTEGER type, then how to encode the name of the Entity class in it? For this, another annotation is used - @DiscriminatorValue .
Look at an example:
@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;
}
In the example above, we told Hibernate that the discriminator will use the user_type column, which will store numbers. If it stores the value 1, then it means that the row type is Employee, if 2 is stored, then the row type is Client. Simple and beautiful.
@DiscriminatorValue
But that's not all. You can tell Hibernate how to interpret the type of a string when its discriminator is NULL.
It's actually very simple. You specify the null value for the @DiscriminatorValue annotation . For example, like this:
@DiscriminatorValue("null")
Class example:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
We've told Hibernate that any table row that has NULL in the user_type column should be interpreted as an object of type User.
But that's not all. There is another interesting value for the @DiscriminatorValue annotation.
Here is this:
@DiscriminatorValue("not null")
Class example:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("not null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
With this annotation, we told Hibernate that any table row with a non-NULL value in the user_type column should be interpreted as an object of type User. But this is only for the case if a class is not found that has the required number explicitly specified.
This is how it will work for different values of the discriminators:
- 0 - create an object of type User
- 1 - create an object of type Employee
- 2 - create an object of type Client
- 3 - create an object of type User
- 4 - create an object of type User
@DiscriminatorFormula
But that's not all. For our discriminator, we can specify an integer formula by which it will calculate the values for the @DiscriminatorValue annotation .
There is a special annotation for this, it is called @DiscriminatorFormula .
Example:
@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;
}
The values returned by @DiscriminatorFormula will be compared by Hibernate with the values specified in the @DiscriminatorValue annotations . With it, you can write quite complex scenarios:
@DiscriminatorFormula(
"case when address is not null " +
"then 'Client' " +
"else (" +
" case when occupation is not null " +
" then 'Employee' " +
" else 'Unknown' " +
" end) " +
"end "
)
GO TO FULL VERSION