I have 3 entities in a Hierarchy like this:
MyInterface
|
-----------------
| |
Entity1 Entity2
The MyInterface is NOT mapped in Hibernate (because I am using implicit polymorphism strategy to map this inheritance)
And, in fact, if I launch a query like this one:
"FROM MyInterface"
It works just fine (because it retrieves all the instances of Entity1 and all the instances of Entity2, puts them together, and returns a List<MyInterface>
).
If we look at the SQL generated by Hibernate, it is launching 2 independent SQL queries to first retrieve the Entity1 instances an another one to retrieve Entity2 instances, but I am fine with this.
The BIG problem comes when you try to do something like this:
"FROM MyInterface ORDER BY someField"
Because it is applying the ORDER BY to the first SQL query and then the same ORDER BY to the second SQL query, instead of apply them to the WHOLE query (I know this because I can see the native SQL queries launched by Hibernate).
This is clearly a missbehaviour of Hibernate.
How can I work around this to force Hibernate to apply the ORDER BY to the whole query? (I cannot do it in memory because later I will have to add pagination also).
The way you are thinking cannot be mapped to SQL as is. Suppose you have
Entity1
with fieldsfield1A
,field1B
... andEntity2
with fieldsfield2A
,field2B
, ... Now you want the following query to be executed:which is not possible in SQL world, as entities have different number of fields and different field types.
So you need to think about extracting common fields into separate table
CommonEntity
, converting your interface into standalone entity with with one-to-one mapping toEntity1
&Entity2
(see Table per subclass). Then SQL will look like:Or you can create a view over your tables and introduce an artificial discriminator (discriminator is something which will "distinguish" IDs from different tables, which caused a problem in your solution) and then map an entity to this view (so we get Table per class hierarchy):
Other alternatives (e.g. mentioned by @UdoFholl which is also kind of "outer join" for
EntityAandEntityB
) will result 2 SQLs and thus there is no way to order the "whole" query, and scrolling is not possible.Hibernate will do this for you if you use the following.
Then have your subclasses that do this
You should then be able to write a query like this to get a single union SQL query with the DB doing the ordering.
I'd say the problem is that Hibernate has to create those 2 SQL queries because you have to read from 2 tables.
I'm not sure if reading from 2 tables and ordering by 2 columns (one from each table) in one query is possible in plain SQL (means no vendor specific extensions), and if not, Hibernate would have to do the ordering in memory anyways.
What you could do when applying paging is: read the ids and the values you want to sort by only (not the entire entity), then sort in memory and read the entire entity for all ids contained in the page. For paging to be consistent you might have to store the results of that initial query (id + order criteria) anyways.