1

OK, this looks mostly like (another) bug/unimplemented functionality in Hibernate.

Is it possible to map a Set association in such a way that the "order by" clause in HQL is respected?

For example, say you have 2 entities: PageEntity and QuestionEntity. A page has a Set.

How do I make the following HQL work:

from
    PageEntity p
        left outer join fetch p.questionEntities q
order by
    q.orderIndex

What I don't want:

  • to use sort in Java (we have "order by" in SQL so we don't have to do this!). SortedSet, Comparators etc. are out of the question
  • to map it as a List with a <list-index>. This will add the "order by" to all SQL queries, and I don't want this
  • to use a <set order-by="orderIndex"> because again, this will be applied to all queries

Debugging, I see that the implementation of Set that is being used is org.hibernate.collection.PersistentSet which wraps a Set. The implementation of the wrapped Set is HashSet. I would expect Hibernate to be smart enough to use a LinkedHashSet instead, so that it can honor my "order by" HQL clause.

3 Answers3

2

I'm pretty sure Hibernate can't do this for you, and would recommend using a List instead. To remove duplicates introduced by the join, you can use the distinct keyword. The resulting List will be just as good as any Set.

If you still need them in an ordered Set (maybe there's a 3rd party API involved) you could create your own LinkedHashSet and move all objects there:

List<PageEntity> list = runQuery(...);
return new LinkedHashSet<PageEntity>(list);
Martin
  • 33,250
  • 14
  • 68
  • 78
0

It seems you want to get results sorted by q.orderIndex but

  • do you want the resulting list of PageEntity to be sorted?
  • or (as I think) do you want the set of QuestionEntitys for each PageEntity to be sorted?

If you want the latter: Sets in Java do not preserve order.

After your edit: no Hibernate does not have to be smart: if you define your collection to be a Set it will be treated as a set. There are many applications where preserving the order costs resources and is not needed.

Matteo
  • 13,467
  • 9
  • 63
  • 103
  • So there is no way to have control over when an association is ordered depending on the "order by" HQL clause? – Cristian Vasile Mocanu Sep 13 '11 at 16:02
  • There is way to have a Set ordered. The Java Specs clearly say that using a Set the order is not guaranteed. If you iterate on a Set you can get element in any order. – Matteo Sep 13 '11 at 16:03
  • The Specs also says that the iteration order for a LinkedHashSet is always stable. – Cristian Vasile Mocanu Sep 14 '11 at 11:06
  • Yes nowhere is specified that Hibernate `PersistentSet` should be a `LinkedHashSet`. See http://stackoverflow.com/questions/4243865/does-hibernate-preserve-the-order-of-a-linkedhashset-and-if-so-how – Matteo Sep 14 '11 at 11:12
0

order by applies to the results of the query. Not to the entities in the collection of questions. I don't think it's a bug: what would it do if one of the returned page entity is already loaded in the session, using another query with another order by clause?

If you want an ordered list of questions, select the questions:

select q from QuestionEntity q inner join fetch q.page p order by q.orderIndex

or

select p, q from PageEntity p
left outer join fetch p.questionEntities q 
order by q.orderIndex

should do the trick.

JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174