Hibernate Tips: How to select a specific subclass from an inheritance hierarchy

Get access to all my video courses, 2 monthly Q&A calls, monthly coding challenges, a community of like-minded developers, and regular expert sessions.
Join the Persistence Hub!
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 leave a comment below.
Question:
I have a many-to-many association to the superclass of an inheritance hierarchy. How can I select only a certain subclass from that hierarchy?
Solution:
You can use a TYPE expression in your JPQL query to limit your query result to one or more subclasses. Let’s take a look at an example.
Authors can write different kinds of Publications, like a Book or a BlogPost. You can model that with an inheritance hierarchy and a many-to-many association between the Author and the Publication entity. In this example, I map the inheritance hierarchy with the InheritanceType.SINGLE_TABLE strategy. So, all entities of the hierarchy are mapped to the same table.

Let’s select all Books that were written by a specific Author. I, therefore, join the Author and Book entities in the FROM clause, check that the Author‘s firstName is equal to ‘Thorben’ and use a TYPE expression to select only Book entities.
Query q = em.createQuery("SELECT b FROM Author a JOIN a.publications b WHERE a.firstName = 'Thorben' AND TYPE(b) = Book"); Book b = (Book) q.getSingleResult(); log.info(b);
As you can see in the log output, Hibernate uses the discriminator column of the Publication table in the WHERE clause to only select Book entities.
13:02:22,453 DEBUG [org.hibernate.SQL] - select publicatio2_.id as id2_1_, publicatio2_.publishingDate as publishi3_1_, publicatio2_.title as title4_1_, publicatio2_.version as version5_1_, publicatio2_.numPages as numPages6_1_, publicatio2_.url as url7_1_, publicatio2_.DTYPE as DTYPE1_1_ from Author author0_ inner join PublicationAuthor publicatio1_ on author0_.id=publicatio1_.authorId inner join Publication publicatio2_ on publicatio1_.publicationId=publicatio2_.id where author0_.firstName='Thorben' and publicatio2_.DTYPE='Book'
Learn more:
If you’re using JPQL, you might also be interested in my detailed guide about it: Ultimate Guide to JPQL Queries with JPA and Hibernate.
And I also wrote a tutorial about JPA’s different strategies to map inheritance hierarchies: Complete Guide: Inheritance strategies with JPA and Hibernate.
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!
Responses