search though all tables extended from @MappedSuperclass

Viewed 233

I have and issue with searching in entities that are extended from @MappedSuperclass. I created a class PhoneBook and extended 2 entities from it: FirstPhoneBook and SecondPhoneBook. The structure looks the following:

@MappedSuperclass
public abstract class PhoneBook {
...

@Entity
@Table(name = "first_phone_book")
public class FirstPhoneBook extends PhoneBook {
...

@Entity
@Table(name = "second_phone_book")
public class SecondPhoneBook extends PhoneBook {
...

These tables are absolutely similar. I discribe all fields in PhoneBook class, childs have only default constructor in it. External system sends a phone number as a parameter. Depending on whether tables contain such number or not my system responds with a word.

The question is: how can I search separately in each table that is extended from @MappedSuperclass without hardcoding each child class name?

I could only find variants of search by value like that:

currentSession.get(Employee.class, theId);

but there is explicit call to entity class. I want this to be extendable without need to write new DAO for each new entity added. Current method signature looks the following:

public <T extends PhoneBook> T findByNumber(String number);

1 Answers

What you describe is polymorphic queries, i.e. queries that reference the parent class. The Hibernate documentation says this is not well supported when using @MappedSuperclass inheritance:

Because the @MappedSuperclass inheritance model is not mirrored at the database level, it’s not possible to use polymorphic queries referencing the @MappedSuperclass when fetching persistent objects by their base class.

If polymorphic queries are frequently used, it's better to use the table per class inheritance strategy:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class PhoneBook {
...

@Entity
@Table(name = "first_phone_book")
public class FirstPhoneBook extends PhoneBook {
...

@Entity
@Table(name = "second_phone_book")
public class SecondPhoneBook extends PhoneBook {
...

You can then fetch an entity using the superclass:

PhoneBook phoneBook = currentSession.get(PhoneBook.class, theId);

and Hibernate would typically use a UNION to do the query with both tables.

This being said, even with @MapperSuperclass, Hibernate can still query all tables for classes that extend the parent class. You can use the following JPA query (note that it uses the fully qualified class name of the parent class):

Query<PhoneBook> query = currentSession.createQuery("from " + PhoneBook.class.getName() +
                                                    " where id = :id", PhoneBook.class);
query.setParameter("id", theId);

The difference is that here it's not querying an entity, but just all classes that extend a parent class. Also in this case, unlike with the table-per-class strategy, Hibernate will not use a UNION, but send a query to each table, in this case two separate SQL queries instead of one.

Related