The best way to use entity inheritance with JPA and Hibernate

(Last Updated On: January 4, 2018)


Recently, my friend Lukas Eder wrote the following message on Twitter:

Just like in any OOP (Object-Oriented Programming) language, entity inheritance is suitable for varying behavior rather than reusing data structures, for which we could composition. The Domain Model compromising both data (e.g. persisted entities) and behavior (business logic), we can still make use of inheritance for implementing behavioral software design pattern.

In this article, I’m going to demonstrate how to use JPA inheritance as a means to implement the Strategy design pattern.

Domain Model

Considering we have a notification system that needs to send both email and SMS to customers, we can model the notification relationships as follows:

Both the SmsNotification and EmailNotification inherit the base class Notification properties. However, if we use a RDBMS (relational database system), there is no standard way of implementing table inheritance, so we need to emulate this relationship. Usually, there are only two choices:

For this example, we are going to use the JOINED table approach which has the following database entity relationship diagram:

Bridging the gap

With JPA and Hibernate, mapping the OOP and the RDBMS models is straightforward.

The Notification base class is mapped as follows:

@Table(name = "notification")
    strategy = InheritanceType.JOINED
public class Notification {

    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Temporal( TemporalType.TIMESTAMP )
    @Column(name = "created_on")
    private Date createdOn;

    //Getters and setters omitted for brevity

The SmsNotification and EmailNotification mappings looks like this:

@Table(name = "sms_notification")
public class SmsNotification 
    extends Notification {

        name = "phone_number", 
        nullable = false
    private String phoneNumber;

    //Getters and setters omitted for brevity
@Table(name = "email_notification")
public class EmailNotification 
    extends Notification {

        name = "email_address", 
        nullable = false
    private String emailAddress;

    //Getters and setters omitted for brevity

Business logic

So far, we only mapped the relationship between the OOP and the RDBMS data structures, but we haven’t covered the actual business logic which is required to send these notifications to our users.

For this purpose, we have the following NotificationSender Service components:

The NotificationSender has two methods:

  • appliesTo gives the entity that’s supported by this NotificationSender
  • send encapsulates the actual sending logic

The EmailNotificationSender is implemented as follows:

public class EmailNotificationSender 
    implements NotificationSender<EmailNotification> {

    protected final Logger LOGGER = LoggerFactory.getLogger( 

    public Class<EmailNotification> appliesTo() {
        return EmailNotification.class;

    public void send(EmailNotification notification) { 
            "Send Email to {} {} via address: {}",

Of course, the actual sending logic was stripped away, but this is sufficient to understand how the Strategy pattern works.

However, the user does not have to interact with the NotificationSender directly. They only want to send a campaign, and the system should figure out the subscriber channels each client has opted for.

Therefore, we can use the Facade Pattern to expose a very simple API:

The NotificationSenderImpl is where all the magic happens:

public class NotificationServiceImpl 
    implements NotificationService {

    private NotificationDAO notificationDAO;

    private List<NotificationSender> notificationSenders;

    private Map<Class<? extends Notification>, NotificationSender> 
        notificationSenderMap = new HashMap<>();

    @SuppressWarnings( "unchecked" )
    public void init() {
        for ( NotificationSender notificationSender : notificationSenders ) {

    @SuppressWarnings( "unchecked" )
    public void sendCampaign(String name, String message) {
        List<Notification> notifications = notificationDAO.findAll();

        for ( Notification notification : notifications ) {
                .get( notification.getClass() )
                .send( notification );

There are several things to note in this implementation:

  • We make use of Spring List auto-wiring feature which I explained in my very first blog post. This way, we can inject any NotificationSender the user has configured in our system, therefore decoupling the NotificationService from the actual NotificationSender implementations our system us currently supporting.
  • The init method builds the notificationSenderMap which takes a Notification class type as the Map key and the associated NotificationSender as the Map value.
  • The sendCampaign method fetches a List of Notification entities from the DAO layer and pushes them to their associated NotificationSender instances.

Because JPA offers polymorphic queries, the findAll DAO method can be implemented as follows:

public List<T> findAll() {
    CriteriaBuilder builder = entityManager

    CriteriaQuery<T> criteria = builder
        .createQuery( entityClass );
    criteria.from( entityClass );

    return entityManager
        .createQuery( criteria )

The system does not have to know which are the actual Notification implementation each client has chosen. The polymorphic query is figured out at runtime by JPA and Hibernate.

Testing time

If we created the following Notification entities in our system:

SmsNotification sms = new SmsNotification();
sms.setPhoneNumber( "012-345-67890" );
sms.setFirstName( "Vlad" );
sms.setLastName( "Mihalcea" );

entityManager.persist( sms );

EmailNotification email = new EmailNotification();
email.setEmailAddress( "" );
email.setFirstName( "Vlad" );
email.setLastName( "Mihalcea" );

entityManager.persist( email );

And now we want to send a campaign:

    "Black Friday", 
    "High-Performance Java Persistence is 40% OFF" 

Hibernate executes the following SQL query:

SELECT AS id1_1_,
    n.created_on AS created_2_1_,
    n.first_name AS first_na3_1_,
    n.last_name AS last_nam4_1_,
    n1_.email_address AS email_ad1_0_,
    n2_.phone_number AS phone_nu1_2_,
    END AS clazz_
    notification n
    email_notification n1_ ON =
    sms_notification n2_ ON =

And the following output is logged:

EmailNotificationSender - Send Email to Vlad Mihalcea via address:

SmsNotificationSender - Send SMS to Vlad Mihalcea via phone number: 012-345-67890

Cool, right?

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.


Entity Inheritance is a very useful technique, but only when you use it along with a behavioral software design pattern, such as Strategy or Visitor pattern.

If you only need to propagate certain properties from a base class to all subclasses, you don’t need JPA entity inheritance. All you need is the @MappedSuperclass annotation, but that’s not entity inheritance since the object hierarchy is only visible in the OOP domain, not in the relationship model.

Subscribe to our Newsletter

* indicates required
10 000 readers have found this blog worth following!

If you subscribe to my newsletter, you'll get:
  • A free sample of my Video Course about running Integration tests at warp-speed using Docker and tmpfs
  • 3 chapters from my book, High-Performance Java Persistence, 
  • a 10% discount coupon for my book. 
Get the most out of your persistence layer!


14 thoughts on “The best way to use entity inheritance with JPA and Hibernate

  1. Hello, I like your blog!

    I have a question related to this article. Can you take a look?

    I have Hotel, Manager, Client, entities and they are referenced from common entities with @ManyToOne or @OneToOne (Address, Contact, Person etc.).

    Lets consider Contact. Each Contact should refer to Hotel or Manager or Client. In this example class I have Hotel class referred

    public class Contact extends CommentedEntity {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = “hotel_id”)
    private Hotel hotel;
    private String contactData;

    To make Contact refer to all 3 classes I could use parent class HaveContact with @Inheritance and extend from it Hotel, Manager, Client.

    Next I need Person refer to Manager or Client, but not Hotel. I would create new parent class HavePerson with @Inheritance but java not allows to inherit Client from two classes HaveContact and HavePerson. I could go with interfaces instead of super class as I can have few interfaces implemented on one class, but Hibernate will not map @ManyToOne on Interface field.

    Is it possible at all to make Contact refer to Hotel, Manager, Client and Person refer to Manager, Client?

    1. If you like my blog, you are going to love my book even more and you can find the answer to what’s the best way to map entity associations as well. Enjoy reading it.

  2. Hi,

    I have a single table inheritance use case as follow:

    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    public class BaseCustomer{
    public class Customer extends BaseCustomer {
    public interface BaseCustomerRepository extends JpaRepository{

    baseCustomerRepository.findAll() return collection of mixture of proxy object and real entity object. In the case of proxy object, it is a proxy object of BaseCustomer instead of Customer, how do you solve this problem?

    1. That would only happen if you have previously loaded a BaseCustomer like this:

      BaseCustomer customer = baseCustomerRepository.getOne(customerId);

      and if the BaseCustomerRepository is declared like this:

      BaseCustomerRepository implements JpaRepository<BaseCustomer, Long>

      A Proxy will always be returned if you loaded it previously, even if the current query ResultSet will contain the right data.

      So, you can fix this issue by revising what you are loading and detaching that prior to executing the query.

      1. Thanks for your prompt response.

        Yes , my BaseCustomerRepository extends JpaRepository<BaseCustomer, Long>. This would only happen if u previously loaded BaseCustomerRepository .getOne() method? How about other self declared method like findByCode(String code), will it also cause the same problem?

        How about if i have another repository CustomerRepository extends JpaRepository<Customer, Long> and i load the entity by calling its getOne() method, will it return the proxy of base object?

        Please advice what should be the design of Repository to prevent such problem happened.

      2. Proxies can be loaded also via @ManyToOne or @OneToOne lazy associations or if you previously used entityManager.getReference calls.

        Nevertheless, as long as the Session is open, the Proxy can always be initialized, so I don’t see what’s the problem.

      3. Yes, there are @ManyToOne lazy fetch declare, how can we generically initialize the proxy during lazy initialization? Quite often the lazy initialization happened when jsp try to access the lazy fetched property, how to initialize the proxy in this case? Is there a centralized way to solve this case for all manyToOne and oneToOne lazy association?

      4. Actually the problem I faced is not lazy initialize exception. The problem I faced is findAll() method return a mixture of proxy object(baseCustomer proxy object) and actual entity(customer). When jsp try to access a property from Customer, it fail to find the getter due to the baseCustomer proxy is unproxy to baseCustomer object. This problem happened for entity inheritance case.

  3. Thank you for these tutorials and the work that has been put into them.
    They are much appreciated and I’m sure are helping tons of people out there.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.