You're right.
So, here is an attempt to reformulate the problem :
Let's say I have an HtmlPage entity.
To this entity, I need to attach ImageFile
s.
So, I can design the following mapping :
Code:
<class name="com.acme.HtmlPage" table="pages">
<id name="unid" column="unid" type="java.lang.String">
<generator class="uuid.hex"></generator>
</id>
<property name="text" type="java.lang.String" column="text"/>
<map name="images" table="pages_images" lazy="true" sort="unsorted" inverse="false" cascade="all" order-by="file_name">
<key column="page_unid"></key>
<index column="file_name" type="string"/>
<composite-element class="com.acme.ImageFile">
<property name="name" type="java.lang.String" column="name"/>
<property name="bytes" type="binary" column="bytes"/>
</composite-element>
</map>
</class>
Now, I have a servlet that renders the images, given the page id, and the file name.
I want to make the HQL query as efficient as possible, and I don't want to make the ImageFiles objects entities. I want them to remain conponents (reasons given above).
As the pages_images already has all the information to retrieve the right Image file, the following query works fine in a single fetch and without promoting the ImageFile as an entity :
Code:
select elements(page.images) from HtmlPage page where page.id=:unid and name=:name
This works but the name= in the where clause isn't well qualified ... and I don't know how to qualify it.So, now, if I add a name property to the page, the query will fail with a
java.sql.SQLException: ERROR: Column reference "name" is ambiguous.
If I try gavin's proposition :
Code:
from HtmlPage page join page.image img where page.id=:unid and img.name=:name
I get a ClassCastException, as I'm retrieving HtmlPages and not the Image.
And if I try :
Code:
select elements(page.images) from HtmlPage page join page.image img where page.id=:unid and img.name=:name
First, it generates an SQL query with a join (that could be avoided), and the query is buggy and returns ALL the images for that page.
The reason for that bug is that Hibernate doesn't understand that the the "elements(page.images)" and "pageimage as img" are the same.
So, it makes 2 aliases in the SQL, and thus, the image.name=:name part of the WHERE clause in the SQL is useless.
Here is the generated SQL, where you can see images
1_ and images
2_ aliases :
Code:
select images2_.name as x0_1_, images2_.bytes as x0_2_ from pages pages0_ inner join pages_images images1_ on pages0_.unid=images1_.page_unid, pages_images images2_ where pages0_.unid=images2_.page_unid and ((pages0_.unid=? )and(images1_.name=? ))
I also tried the following HQL that could solve the problem :
Code:
select elements(page.images) as img from HtmlPage page where page.id=:unid and img.name=:name
But it fails too with a QueryException : ", expected in SELECT".
As far as I understand the inner working of Hibernate, all the above problems are "normal", and I think only the last query with select elements(...)
as img could solve the problem.
It doesn't seem to be supported though :-(
But as I'm still a beginner in Hibernate, I might miss an important point.
Thanks again for your help.