How can I mix inheritance strategies (SINGLE_TABLE and TABLE_PER_CLASS) with Hibernate 6.4/JPA?

I am trying to design an entity model with inheritance that also supports maintaining draft and publish states of the entities. I am using JPA annotations with Hibernate implementation (version 6.5). I have the following entity model

  • abstract Message
    • abstract TextRoot
      • Text
        • TextPublish
        • TextDraft
    • abstract WhatsappRoot
      • Whatsapp
        • WhatsappPublish
        • WhatsappDraft

Here is what I want to achieve

  • all of the classes here are entities and I want to support polymorphic queries (i.e. fetch all Messages or fetch all Texts)
  • I want to create tables for all of the entities I have highlighted in bold to represent a single table for each sub hierarchy
  • The entities highlighted in bold will have “publish” and “draft” entities and the entities highlighted in bold will have tables that contain both publish and draft entities

I tried using a mix of two JPA inheritance strategies, SINGLE_TABLE and TABLE_PER_CLASS.
I annotated Message with TABLE_PER_CLASS and annotate Text and Whatsapp with SINGLE_TABLE. I do understand as per JPA spec it isn’t recommended. However, I believe I need both strategies because I need an inheritance strategy to be applied to the root class so that I can tell Hibernate I want to support polymorphic queries at that level but create a table per “sub hierarchy” by using SINGLE_TABLE.
In the end it didn’t work as expected - Hibernate seems to ignore the SINGLE_TABLE inheritance strategy and generate DDLs using only the TABLE_PER_CLASS inheritance strategy applied on the Message entity class.

Can anyone suggest how I try to achieve a mixed inheritance strategy for my use case?

You cannot use different inheritance strategies in the same inheritance hierarchy. The @Inheritance annotation, used to specify which InheritanceStrategy to use, must be placed on the root entity type and will be used for all the child entities.

Looking at your class list, it would fit to use @MappedSuperclasses, instead of single-table inherited entities, but not that this will mean not having a corresponding table on the database-side. If you still want to maintain separate tables even for the abstract root classes, you’re going to have to choose either the single-table or the table-per-class strategy for the whole hierarchy.

1 Like

Firstly, thank you for your reply! I appreciate it.
So, if i use @MappedSuperclass, wouldn’t it be rather impossible to use polymorphic queries on those classes as they wont be annotated with @Entity?

No, it won’t. Hibernate supports polymorphic HQL queries across @MappedSuperclass types. You won’t be able to fetch superclass-typed entities through normal Session methods, though, e.g. session.find( id, MappedSuperclassType.class ) will not work.