The best way to map the @DiscriminatorColumn with JPA and Hibernate

Introduction

As previously explained, the SINGLE_TABLE inheritance is the most efficient entity inheritance strategy.

However, for JPQL query such as this one:

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "where p.board = :board", Post.class)
.setParameter("board", board)
.getResultList();

Hibernate generates a SQL query which filters by the associated discriminator column (e.g. DTYPE by default):

SELECT t.id AS id2_1_,
       t.board_id AS board_id8_1_,
       t.createdOn AS createdO3_1_,
       t.owner AS owner4_1_,
       t.title AS title5_1_,
       t.content AS content6_1_
FROM   topic t
WHERE  t.DTYPE = 'Post'
       AND t.board_id = 1

So, because we are filtering by the discriminator column, we might want to index it or include it to speed up queries.

However, the default STRING DiscriminatorType expects a VARCHAR column that must hold the longest entity subclass name. For the Announcement class, we need at least 12 bytes to store the entity class name while for the Post entity, 4 bytes are required.

If the discriminator type column is indexed and we store 1 million Announcement and 100 million Post entities, the index will require 393 MB (12 + 400 million bytes). On the other hand, if the discriminator column is a TINYINT (only 1 byte is needed to store a discriminator value), we need only 96 MB (1 + 100 million bytes).

In this article, I’m going to explain how you can get the most out of the INTEGER DiscriminatorType while still retaining the descriptiveness of the default STRING DiscriminatorType.

Continue reading “The best way to map the @DiscriminatorColumn with JPA and Hibernate”

Advertisements

The best way to map the SINGLE_TABLE inheritance with JPA and Hibernate

Introduction

Java, like any other object-oriented programming language, makes heavy use of inheritance and polymorphism. Inheritance allows defining class hierarchies that offer different implementations of a common interface.

Conceptually, the Domain Model defines both data (e.g. persisted entities) and behavior (business logic). Nevertheless, inheritance is more useful for varying behavior rather than reusing data (composition is much more suitable for sharing structures).

Even if the data (persisted entities) and the business logic (transactional services) are decoupled, inheritance can still help varying business logic (e.g. Visitor pattern).

In this article, we are going to see what is the best way to map the SINGLE_TABLE inheritance, which, not only is the default inheritance strategy, but it’s usually the most efficient way to model entity inheritance.

Continue reading “The best way to map the SINGLE_TABLE inheritance with JPA and Hibernate”