Description

Each of the above strategies and techniques has its own advantages and disadvantages. General recommendations for choosing a specific strategy will look like this:

TABLE_PER_CLASS strategy based on UNION

This strategy is best chosen if polymorphic queries and associations are not required. If you rarely do (or don't do at all) "select user from User user". If you don't have any Entity classes that refer to User, this is the best option (since you can still add optimized polymorphic queries and associations).

SINGLE_TABLE strategy

This strategy should be used:

a) Only for simple tasks. In situations where normalization and the NOT NULL constraint are critical, strategy #3 (JOINED) should be preferred. It makes sense to think about whether in this case it is not worth completely abandoning inheritance and replacing it with delegation.

b) If polymorphic queries and associations are required, as well as dynamic definition of a concrete class at run time. At the same time, subclasses declare relatively few new fields, and the main difference with a superclass is in behavior.

And on top of that, you have a serious conversation with the DBA.

JOINED strategy

This strategy is the most efficient in terms of speed and CONSTRAINTS. It is suitable in cases where polymorphic queries and associations are required, but subclasses declare relatively many new fields.

A word of caution here: the decision between JOINED and TABLE_PER_CLASS requires evaluation of query execution plans on real data, since the width and depth of the inheritance hierarchy can make the cost of joins (and, as a result, performance) unacceptable.

Separately, it is worth taking into account that inheritance annotations cannot be applied to interfaces.

EXPLICIT

There may also be a situation where you have a hierarchy of Entity classes with a shared storage strategy in the database. But for whatever reason, you don't want some hierarchy class to be returned when a query is made on the base class.

There is an annotation for this:

@Polymorphism(type = PolymorphismType.EXPLICIT)

If we add it to the Client class :

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
@Polymorphism(type = PolymorphismType.EXPLICIT)
class Client extends User {
   String address;
}

Then HQL queries will ignore objects of this class when querying the base class:

List<User> accounts = session.createQuery("from User").getResultList();

This query will return a list of User and Employee objects , but not Client .