Saturday, 5 September 2015

LEFT JOIN FETCH returns double results

I recently got a Bugreport from my manager that she was seeing double rows in one of our screens. After a little research I found the culprit to be the following (paraphrased) HQL query.

SELECT order from Order order LEFT JOIN FETCH order.items

The resultset returned from the database will look like this:
As you can see, the order appears twice, once for each order item.

What we want to get from Hibernate is:

What we get from hibernate is:
However, this is by design. As you can see you get two Orders, but they both refer to the same instance. Things are as it should be.

To fix this, see the great answer by Gavin King1 or on StackOverflow2.

When changing the result into:
SELECT DISTINCT order from Order order LEFT JOIN FETCH order.items
The double rows disappears, however the distinct does go through to the database (where it does nothing, as the rows are already distinct) however, it also adds the ResultTransformer implicitly, causing me to get the one row as designed.

Talked about it with the Architect, he doesn't like the use of 'distinct' in HQL queries, because:
  • it is unclear how it will be processed (locally or in the database)
  • may be a cause for performance issues if the distinct is forwarded to your database
  • In general, if you need a 'distinct' in your query to defeat double data, chances are that the query could use some improvements
With an explicit ResultTransformer, the code looks like the following:
List result = session.createQuery("select o from Order o left join fetch o.items"
And the problem is fixed.


[1] JBoss - Hibernate FAQ
[2] StackOverflow - Hibernate Criteria returns children multiple times with FetchType.EAGER

No comments:

Post a Comment