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 a 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.
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:
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:
"High-Performance Java Persistence is 40% OFF"
Hibernate executes the following SQL query:
n.id 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_,
CASE WHEN n1_.id IS NOT NULL THEN 1
WHEN n2_.id IS NOT NULL THEN 2
WHEN n.id IS NOT NULL THEN 0
END AS clazz_
LEFT OUTER JOIN
email_notification n1_ ON n.id = n1_.id
LEFT OUTER JOIN
sms_notification n2_ ON n.id = n2_.id
And the following output is logged:
EmailNotificationSender - Send Email to Vlad Mihalcea via address: email@example.com
SmsNotificationSender - Send SMS to Vlad Mihalcea via phone number: 012-345-67890
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.