Last time we have taken a look at mapping entity relations to the database. Now it is time to focus on the main object-orinented relation: inheritance.
As you already know, objects can inherit from each other to move common functionality into a superclass and have only the different parts in the children. The same can be achieved with Hibernate too: you can group common functionality to a parent class and add only the differences to the children — and you can map this relation to the database too.
I will continue the example with the books — however this means the example for now is a bit hard to digest but I try to make it more comfortable for you.
Persons, authors and publishers
First I thought about Book-inheritance but I ended up with a simple inheritance model of persons which can be authors and publishers. Each person has a name (this is the primary identifier) and an email address.
Authors maintain a list of the books written and a reference of their publisher (every author can have only one publisher). Publishers have a tax ID and a list of their authors.
Single table inheritance
The first inheritance model is the single table. This stores every subclass (like the name suggests) in a single database table. This means that you cannot apply database level constraints on the required columns of child classes because other children do not have this field and this would throw and integrity violation exception.
To tell an entity structure to work with the single table inheritance add the following code on the base entity’s definition:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
To distinguish between the entity types stored in the single table Hibernate (and JPA generally) uses a discriminator column. If you do not provide the definition of the discriminator column Hibernate uses a string column named DTYPE which has a length of 31 characters.
The default value of the discriminator column is the entity’s name, so in this example there are two discriminators: Author and Publisher.
With the usage of @DiscriminatorColumn and @DiscriminatorValue you can override these defaults to fit your schema and requirements.
The second type is the joined inheritance. In this case the subclasses are stored in separate database tables with the ID as a common identifier where Hibernate can join the requested children together with the base class.
To create a joined inheritance, simply add the following to the parent-class definition:
@Inheritance(strategy = InheritanceType.JOINED)
Table per class inheritance
The third type is the table per class model where every instance gets its own table with every information in it. This means big redundancy and violates the database normalization rules because all information of the parent class(es) are stored for every instance in a single table.
In the example Authors store name, emailAdress and publisherId, the Publishers store name, emailAdress and taxId.
And there is no table created for the abstract class storing the persons because Hibernate knows that the AbstractPerson entity is abstract so it does not need any table to store information.
Table-per-class inheritance can be used with the following annotation over the superclass:
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
Which one to use?
This depends on your application. However I’ve never seen any application utilizing the table per class strategy in the application, only joined or single table. Sometimes big inheritance trees can result in big join queries created by Hibernate and sometimes it is slower than a single table solution.
However sometimes the better way is to skip Hibernate and create a query manually to make the result gathering faster and avoid Hibernate’s assumptions on the data structure and how it can gather the information.
Inheritance strategies are good to model the entities to the database with maintained object-oriented design. But this can result in very big and slow queries from Hibernate but this does not mean that you should avoid them.
In the next article I will show you how can you write your own queries for Hibernate with HQL and JPQL because the current ones in the main method aren’t the best.
You can download chapter specific code from Github Here.