Reputation: 18035
I have a @MappedSuperclass
called Data as the parent of every Entity in my database. It contains common attributes like Id etc. I then have an entity that extends Data which is also a @MappedSuperclass
due to common functionality of its subclasses. The mapping in my database is correct.
Here is an example of my hierarchy
@MappedSuperclass Data | @MappedSuperclass +- Employee | | @Entity | +- FullTimeEmployee | | @Entity | +- PartTimeEmployee | @Entity +- Store
And the tables are correctly mapped:
FullTimeEmployee PartTimeEmployee Store
Is there anyway to query the database for all Employee subclasses (FullTimeEmployee, PartTimeEmployee) as instances of Employee without referring the name of the subclasses in the query?
Something like
List<Employee> allEmployees = getAllEmployees();
The idea is that whenever I decide to create another subclass of Employee (i.e. AllDayEmployee) I will not have to change the query to include the name.
So, as Gregory correctly pointed out, this is not possible with @MappedSuperclass
. So I changed it into @Entity and, since I wanted to preserve a table for each subclass I used InheritanceType.JOINED
.
So the above hierarchy is now
@MappedSuperclass Data | @Entity | @Inheritance(strategy=InheritanceType.JOINED) +- Employee | | @Entity | +- FullTimeEmployee | | @Entity | +- PartTimeEmployee | @Entity +- Store
And the tables are still:
FullTimeEmployee PartTimeEmployee Store
So now, to get all Employees I simply call:
entityManager.createQuery("from Employee").getResultList();
Upvotes: 15
Views: 18465
Reputation: 976
I seem to be able to do this (although using InheritanceType.JOINED) with hibernate 5.0.8, java 1.8.0_73 and Oracle 12c - either I am misunderstanding or maybe hibernate has changed..
I have the following hierarhcy:
@MappedSuperclass
@Inheritance(strategy=InheritanceType.JOINED)
CommonRoot
|
| @MappedSuperclass
+- Mapped
| @Entity(name="Concrete1")
| @Table(name="CON1")
+- Concrete1
|
| @Entity(name="Concrete2")
| @Table(name="CON2")
+- Concrete2
And I can do the following HQL:
SELECT entityId FROM com.hibernatetest.Mapped ORDER BY entityId ASC
which gives these 2 SQL statements:
select concrete2x0_.entityId as col_0_0_ from CON2 concrete2x0_ order by concrete2x0_.entityId ASC
select concrete1x0_.entityId as col_0_0_ from CON1 concrete1x0_ order by concrete1x0_.entityId ASC
and the warning
WARN: HHH000180: FirstResult/maxResults specified on polymorphic query; applying in memory!
Not sure what they mean though, as this can be done with SQL as:
(select entityId from CON2
union all
select entityId from CON1)
order by entityId ASC
(And you can also add limit/rownum clauses to that if you desire, although that gets a bit clunky:
select * from (
(select * from (select entityId from CON2 order by entityId ASC) where rownum <= 10)
UNION ALL
(select * from (select entityId from CON1 order by entityId ASC) where rownum <= 10)
) where rownum <= 10 order by entityId ASC
Not sure why hibernate shouldn't be able to do this - might suggest it to them.)
Upvotes: 1
Reputation: 10323
Yes
FROM Employee WHERE Employee.<employee only properties> = someValue
But only, as the others have said here, if the Employee entity is mapped. You don't need to even map it to its' own table. See the mapping strategies in Hibernate.
Upvotes: 0
Reputation: 7261
No if you are using @MappedSuperclass
The reason for this is that when you define base class as @MappedSuperclass, there is no table generated for the base class, instead all of the properties are replicated in the concrete tables. In your example only FullTimeEmployee, PartTimeEmployee and Store tables would exist.
If you want to be able to query for base class entities you need to select different mapping for base classes. Use @Inheritance annotation on the base class and select one of the 3 possible mapping strategies - SINGLE TABLE, TABLE PER CLASS or JOINED
Upvotes: 12