Hibernate Tips: How to override column mappings of a superclass


Take your skills to the next level!

The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.



Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please post a comment below.

Question:

A few days ago, I got an interesting question from one of my Advanced Hibernate Online Training students. He used the @MappedSuperclass strategy to map an inheritance hierarchy to multiple database tables and wanted to change the attribute mapping for one of the subclasses.

So, he asked me: How can I override the attribute mapping in an inheritance hierarchy?

Solution:

Overriding an attribute mapping for a @MappedSuperclass mapping is relatively simple. You can do it in the same way as you override the mapping of an embeddable.

But before we talk about overriding the mapping, let’s first take a quick look at an inheritance mapping that uses the @MappedSuperclass strategy.

Inheritance mappings using @MappedSuperclass

This approach enables you to define shared attributes and their mappings on a superclass without making the superclass an entity. So, the superclass doesn’t get managed by your persistence context and not mapped to a database table. But all of its subclasses can be managed entities, which get mapped to their own database tables.

If you apply this mapping to the following classes, the Publication class isn’t an entity and doesn’t get mapped to a database table. But the Book and the BlogPost entities are entities which get mapped to database tables with the same name.

I explained this and other mapping strategies for inheritance hierarchies in great details in my complete guide to inheritance mappings.

Overriding an attribute mapping

Let’s now change the mapping of the summary attribute of the Book so that it gets mapped to the blurb column of the book table.

You can use the @AttributeOverride annotation on the Book entity to override the mapping of each attribute defined by the Publication class. You only need to provide the name of the attribute for which you want to change the mapping and a @Column annotation.

In this example, I reference the summary attribute and provide a @Column annotation that sets the database column to blurb.

@Entity
@AttributeOverride(name = "summary", column = @Column(name = "blurb"))
public class Book extends Publication { ... }

Testing the mapping

If you then use the Book entity to read or write a database record, as I do in the following test case, you can use all attributes mapped by the Publication superclass.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Book b = new Book();
b.setTitle("Hibernate Tips - More than 70 solutions to common Hibernate problems");
b.setNumPages(250);
b.setPublishingDate(LocalDate.of(2017, 4, 4));
b.setSummary("When you use Hibernate in your projects, you quickly recognize that you need to do more than just add @Entity annotations to your domain model classes...");
em.persist(b);

em.getTransaction().commit();
em.close();

When you activate the logging of the executed SQL statements, you can see that Hibernate uses the mapping defined by the Publication class for all attributes except the summary attribute. The @AttributeOverride annotation on the Book entity changed that mapping to the blurb column.

08:42:19,319 DEBUG [org.hibernate.SQL] - 
    select
        nextval ('hibernate_sequence')
08:42:19,376 DEBUG [org.hibernate.SQL] - 
    insert 
    into
        Book
        (publishingDate, blurb, title, version, numPages, id) 
    values
        (?, ?, ?, ?, ?, ?)
08:42:19,722 DEBUG [org.hibernate.SQL] - 
    select
        book0_.id as id1_2_,
        book0_.publishingDate as publishi2_2_,
        book0_.blurb as blurb3_2_,
        book0_.title as title4_2_,
        book0_.version as version5_2_,
        book0_.numPages as numPages6_2_ 
    from
        Book book0_ 
    where
        book0_.id=?
08:42:19,740 INFO  [org.thoughts.on.java.model.TestInheritance] - Book title: Hibernate Tips - More than 70 solutions to common Hibernate problems

Learn more:

If you liked this article, you might also be interested in:

Hibernate Tips Book

Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.

Get it now!

5 Comments

  1. Avatar photo Thorben Janssen says:

    Hi Nathan,

    unfortunately, you can't remove an entity attribute defined on a superclass on one of its subclasses. You can only change the name of the column.

    Regards,
    Thorben

  2. Thank you very much for this explanation sir.

    I would like to know how an attribute can be completely overridden to be ignored using hibernate annotations. I have tried to using @Transient on subclasses but the annotated fields in the superclasses remain noticed by hibernate in schema creation. I completely want some inherited fields to be completely ignored by hibernate especially when I use desired hibernate annotated subclass fields in schema creation. Thank you in advance for your help.

  3. Avatar photo Vijay Kumar says:

    Is it also possible to override entity identifier strategy while overriding an attribute from the parent class as shown in the above example? Considering the above example, for Book class I want to use override the attribute with a different column name as well as use @SequenceGenerator specific to Book class (assuming Publication class use @GeneratedValue(strategy=GeneratedType.SEQUENCE or any other).

  4. Hi Jansen,
    As for a future Tip subject, could you explain how to manage a delete of a manyToMany association ?
    I had to do that and the solution I found does not seem to be very “clever”.
    I’m sure there is a best pratice to do that.

Comments are closed.