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 "
)
undefined
1
Task
Module 4. Working with databases, level 15, lesson 2
Locked
Single Table Strategy
task1502