1

I am following the hibernate documentation for one-to-many and many-to-one Unidirectional associations with join tables.

I tried to implement a simple example by creating Person & Address entity like this:

Person has an id and name property with setters & getters
Address has an id and name property with setters & getters

I have the same mapping file given in the documentation for one-to-many and also many-to-one. Then I created a small program to get Person entities and the corresponding Address entities like this:

For one-to-many:

    for (Person person : list) {
        System.out.println(person.getId());
        for (Address address : person.getAddresses()) {
            System.out.println(address);    
        }
    }

For this hibernate generated below queries:

Hibernate: select person0_.personId as personId1_1_ 
from Person person0_

Hibernate: select addresses0_.personId as personId1_1_0_, addresses0_.addressId as addressId2_2_0_, address1_.addressId as addressId1_0_1_ 
from PersonAddress addresses0_ 
inner join Address address1_ 
on addresses0_.addressId=address1_.addressId 
where addresses0_.personId=?

For many-to-one:

   List<Person> list = session.createQuery("from Person").list();
            for (Person person : list) {
                System.out.println(person.getId());
                System.out.println(person.getAddress());
            }
Hibernate: select person0_.personId as personId1_1_, person0_.name as name2_1_, person0_1_.addressId as addressId2_2_ 
from Person person0_ 
left outer join PersonAddress person0_1_ 
on person0_.personId=person0_1_.personId

Hibernate: select address0_.addressId as addressId1_0_0_, address0_.name as name2_0_0_ 
from Address address0_ 
where address0_.addressId=?

From the generated queries, for one-to-many initially the query was to get records from Person table to get all Persons then for getting the addresses it had JOIN between PersonAddress and Address.

Where as for many-to-one initially it had LEFT OUTER JOIN between PersonAddress and Address to get Person records then it hit the Address table to get the records from Address table.

So my doubt is why the many-to-one case has not followed the same approach of one-to-many by hitting only Person table because initially I am trying to fetch only Person entities in my HQL. Please help me in understanding this.

learner
  • 6,062
  • 14
  • 79
  • 139

1 Answers1

4

For the OneToMany case, a person has a collection of addresses. The collection could have 0, one or more addresses. This collection is populated lazily. So, when a person is loaded from the database, a first query is executed to get the fields of the person (name, etc.). Hibernate doesn't know yet if the person has addresses or not, and it doesn't care. It sets the addresses collection to a lazy collection. The first time a method is called on this lazy collection, a second query is executed to load all the addresses of the person and populate the collection.

For the ManyToOne case a person has a field address of type Address. When you load a person, what should Hibernate initialize this field to. If it sets it to null and you ask for the address, it will return null, even if the person has an address, which is wrong. If it sets it to an lazy address proxy and you ask for the address, it will return the non-null proxy even if the person doesn't have an address, which is also wrong. So Hibernate has to know if the person has or doesn't have an address. If it doesn't have one, it sets the field to null. If it has one, it sets the address to an address proxy. That's the reason why an additional left outer join is executed: to know if the person has an address or not (and what the ID of this address is, if any).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Hi JB, if possible can you please take a look at my other post --> http://stackoverflow.com/questions/25774357/understanding-hibernate-documentation-on-bidirectional-one-to-many-mapping – learner Sep 10 '14 at 21:04
  • can you please check my other similar query --> http://stackoverflow.com/questions/25800160/why-the-one-to-many-bidirectional-mapping-with-join-table-uses-inner-and-left-ou – learner Sep 14 '14 at 10:36