Hibernate is a very useful framework to do Object-Relational mapping in Java. It saves a lot of time, gives the programmer a lot of flexibility and allows you to do amazing things like mapping object inheritance.
Nevertheless, it has some “strange” behaviours that, in my opinion, seem a bit courterintuitive. I’m going to tell you about the way Hibernate translates object relations into joins.
Let’s imagine we have the class Person, with attributes id and name, and the class Car, with attributes id and brand. Class Person has a one-to-one relationship with Car named car, and there’ll be persons who have a car, and persons who haven’t.
If we want to query about the cars each people have, the “intuitive” query would be this:
select p.name, p.car from Person p
And the “intuitive” result would be: (John, Car instance #1); (Peter, null); (Mary, Car instance #2), isn’t it?
It isn’t. The real thing is that Hibernate translates the HQL sencence to a SQL one that selects from Person and does an (inner) join with Car, in order to instantiate a Car with all its attribute values set up. As a consequence of that inner join, all the people having a null car are missing from the result.
Intuitive solution: force the outer join by hand
select p.name, c.id, c.brand from Person p left join p.car c
Non intuitive (but valid) solution: use the required attributes directly
select p.name, p.car.id, p.car.brand from Person p
In this last query, I would expect a NullPointerException when the person has no car, since if there is no car, there is no attribute to evaluate, but the exception doesn’t get thrown, the problem doesn’t arise and you get the work done.
Quite strange, isn’t it?