JPA: Implementing Model Hierarchy - @MappedSuperclass vs. @Inheritance

37,018

Solution 1

MappedSuperClass must be used to inherit properties, associations, and methods.

Entity inheritance must be used when you have an entity, and several sub-entities.

You can tell if you need one or the other by answering this questions: is there some other entity in the model which could have an association with the base class?

If yes, then the base class is in fact an entity, and you should use entity inheritance. If no, then the base class is in fact a class that contains attributes and methods that are common to several unrelated entities, and you should use a mapped superclass.

For example:

  • You can have several kinds of messages: SMS messages, email messages, or phone messages. And a person has a list of messages. You can also have a reminder linked to a message, regardless of the kind of message. In this case, Message is clearly an entity, and entity inheritance must be used.
  • All your domain objects could have a creation date, modification date and ID, and you could thus make them inherit from a base AbstractDomainObject class. But no entity will ever have an association to an AbstractDomainObject. It will always be an association to a more specific entity: Customer, Company, whatever. In this case, it makes sense to use a MappedSuperClass.

Solution 2

@MappedSupperclass is different than the @Inheritance annotation.

@MappedSuperclass tells the JPA provider to include the base class persistent properties as if they were declared by the child class extending the superclass annotated with @MappedSuperclass.

However, the inheritance is only visible in the OOP world, since, from a database perspective, there's no indication of the base class. Only the child class entity will have an associated mapped table.

The @Inheritance annotation is meant to materialize the OOP inheritance model in the database table structure. More, you can query a base class annotated with @Inheritance but you can't do that for a base class annotated with @MappedSuperclass.

Now, the reason why you'd want to use the @Inheritance JPA annotation is to implement behavior-driven patterns like the Strategy Pattern.

On the other hand, @MappedSuperclass is just a way to reuse both basic properties, associations, and even the entity @Id using a common base class. Nevertheless, you can achieve almost the same goal using an @Embeddable type. The only major difference is that you can't reuse an @Id definition with @Embeddable, but you can do it with @MappedSuperclass.

Share:
37,018
huzeyfe
Author by

huzeyfe

I am a 10+ years experienced Software Developer. Main interests Java, Spring, JSF, Rest & Micro Services.

Updated on January 09, 2021

Comments

  • huzeyfe
    huzeyfe over 3 years

    I am using Play Framework 1.2.4 with PostgreSQL and JPA. I would like to have a Model hierarchy and see that there are some alternatives to doing this.

    I have a base class (which is abstract) and two concrete classes extending this base class. I don't want to persist this base class while I want to have concrete classes. In the base class, I have another Model classes as properties, in other words, I have @ManyToOne relationships in my base class.

    My question is what is the best way of implementing this? Using @MappedSuperclass or @Inheritance with TABLE_PER_CLASS strategy? I am a bit confused as they seem virtually equivalent.

    I also have some concerns about querying and performance issues that I might face in future.

  • huzeyfe
    huzeyfe over 12 years
    Many thanks for your answer. I am now clear on that if I need to persist or use base class as an entity I should use entity inheritance. I wonder if there is a problem with performance or restriction on queries especially using inherited object relations?
  • JB Nizet
    JB Nizet over 12 years
    It all depends on which kind of inheritance you choose, and which inheritance strategy.
  • huzeyfe
    huzeyfe over 12 years
    In my case (as I don't want to persist base class) MappedSuperClass seem more suitable. So in terms of performance and restrictions do I need to be aware of some certain issues?
  • JB Nizet
    JB Nizet over 12 years
    No. It will work exactly as if the mapped superclass attributes were in the entity directly.
  • Bahattin Ungormus
    Bahattin Ungormus over 6 years
    "The only major difference is that you can't reuse an Id definition with Embeddable, but you can do it with MappedSuperclass" thank you, I have been trying to find this for almost an hour.
  • Serafins
    Serafins over 3 years
    The great thing about '@Inheritance' is, that we can use polymorphic queries. Setting '@Inheritance' to TABLE_PER_CLASS, what's a difference between that and '@MappedSuperclass'?
  • Vlad Mihalcea
    Vlad Mihalcea over 3 years
    TABLE_PER_CLASS is very inefficient due to the UNION ALL queries. Better use SINGLE_TABLE or JOINED, as explained in my High-Performance Java Persistence book.
  • Julio Faerman
    Julio Faerman over 2 years
    THANK YOU, makes it much clearer
  • Vlad Mihalcea
    Vlad Mihalcea over 2 years
    @JulioFaerman I'm glad I could help