Trying to understand the importance of an owning side of a one-many relationship in ORM
Asked Answered
J

2

8

Even though my question is worded specifically to the way Entity relationships are depicted in the Play framework, which uses Hibernate, I am sure this is a general concept.

When we have a one-to-many relationship, we are always asked to specify the owning side.

So, for example if we had a one-to-many relationship between Person and PhoneNumber, we would write code like this.

@Entity
class Person {
    @OneToMany(mappedBy="person")
    public Set<PhoneNumber> phoneNumbers;
}

@Entity
class PhoneNumber {
    @ManyToOne
    public Person person;
}

In the code above, the owning Entity is PhoneNumber. What are the pros and cons of either side being the owning entity ?

I realize when the owning entity is PhoneNUmber, the relationship represented is ManyToOne, which will not result in a join table, whereas when the owning side is Person, the relationship depicted would be OneToMany, in which case a relationship table will be created.

Is this the main reason for determining the owning side, or are there other reasons as well ?

Update: I just realized that this thread provides part of the answer, but I am hoping there may be other points as well.

Jiggermast answered 20/12, 2011 at 7:18 Comment(0)
S
1

With most ORM layers you have concept of lazy loading. When you create a Person object it will not load phones set unless asked to. At times how you want to lookup data can also dictate how you store it.

Like if you want to bring up person first and then show phone numbers on demand then keeping person references in phone is fine. First you fire a simple query to load person data and then just lookup phone numbers based on an (already loaded) person.id (another simple query)

Whereas for showing person + phone data at one go, you would prefer having a join table where you can just load data based on person table + person-phone join table using person id as keys into phone table, all in one go. Here it would be expensive to do lookups without a relationship table.

But quite frankly, if you think SQL instead of ORM then you would go with a relationship table every time :D

Slily answered 20/12, 2011 at 7:55 Comment(3)
I am trying to think aloud. Let's say in both cases, we do an eager fetch. For the first case, where PhoneNumber is the owning entity, we will fire the first query to get all Person entities, and then fire individual queries for each Person to get all PhoneNumber's for that Person. However, if we had Person as the owning side, we need fire just one query with a join. I am sorry if this is a silly question, but is a join not possible with Person being an FK in PhoneNumber ?Jiggermast
Yes, the join should be possible with person id FK in phone table as well. Here I am (assuming) that a normalized lookup would be faster but you have to look at your explain plan to be sure. Another reason (at least theoretical) to use a relationship table would be to allow sharing of phone numbers, like a phone number used by two people in shifts. Frankly, How an ORM layer works should be inconsequential for such considerations because no one designs the schema with an ORM layer in mindSlily
see my answer in this thread as well for reasons for the names 'mappedBy' and 'owning side', what happens if we don't define a owning side, GOTCHAs - #2750189Choli
A
6

An important point to keep in mind is that the owning relation is the one that actually persist the relation on save. With an example:

    Person person = new Person();
    PhoneNumber pn = new PhoneNumber();
    pn.phone = "12345678";
    person.phoneNumbers.add(pn);
    session.save(person);

The relation is not save infact if you reload the entity from the database you'll see no numbers. To actually add the relation you need to set the person on the owner side (PhoneNumber) and then save.

    // the relation is not saved
    Person loadedPerson = (Person)session.load(Person.class, person.id);
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 0!

    pn.person = person;
    session.save(pn);

    loadedPerson = (Person)session.load(Person.class, person.id);
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 1
Airplane answered 20/12, 2011 at 11:14 Comment(0)
S
1

With most ORM layers you have concept of lazy loading. When you create a Person object it will not load phones set unless asked to. At times how you want to lookup data can also dictate how you store it.

Like if you want to bring up person first and then show phone numbers on demand then keeping person references in phone is fine. First you fire a simple query to load person data and then just lookup phone numbers based on an (already loaded) person.id (another simple query)

Whereas for showing person + phone data at one go, you would prefer having a join table where you can just load data based on person table + person-phone join table using person id as keys into phone table, all in one go. Here it would be expensive to do lookups without a relationship table.

But quite frankly, if you think SQL instead of ORM then you would go with a relationship table every time :D

Slily answered 20/12, 2011 at 7:55 Comment(3)
I am trying to think aloud. Let's say in both cases, we do an eager fetch. For the first case, where PhoneNumber is the owning entity, we will fire the first query to get all Person entities, and then fire individual queries for each Person to get all PhoneNumber's for that Person. However, if we had Person as the owning side, we need fire just one query with a join. I am sorry if this is a silly question, but is a join not possible with Person being an FK in PhoneNumber ?Jiggermast
Yes, the join should be possible with person id FK in phone table as well. Here I am (assuming) that a normalized lookup would be faster but you have to look at your explain plan to be sure. Another reason (at least theoretical) to use a relationship table would be to allow sharing of phone numbers, like a phone number used by two people in shifts. Frankly, How an ORM layer works should be inconsequential for such considerations because no one designs the schema with an ORM layer in mindSlily
see my answer in this thread as well for reasons for the names 'mappedBy' and 'owning side', what happens if we don't define a owning side, GOTCHAs - #2750189Choli

© 2022 - 2024 — McMap. All rights reserved.