Thursday, February 15, 2007

Hibernate: When is "inverse=true" and when it's not?

When I was a hibernate beginner, I was confused about deciding "inverse=true" or "inverse=false".

Here is an easy way to understanding it:

example scenario:
Person(one) <-> Address(many)
* bi-directional one-to-many relationship. (A person has multiple addresses.)


public class Person {
private Integer id;
private Set<Address> addresses;

// setter, getter
Set<Address> getAddresses() { return addresses; }
....
}


public class Address {
private Integer id;
private Person person;

// setter, getter
Person getPerson() { return person; }
.....
}
  • Person class has "Set<Address> getAddresses()" method
  • Address class has "Person getPerson()" method

If you think about the relation between two classes, it may gives an idea that person has addresses. (Person -> Addresses)
So, it feels like a person is an owner, and an address is a child. Then, you want to think that address is "inverse=true" because address is owned by person.
However, it's not correct.


Here, I'd like to suggest a way to think about it.

Let's look at table structure instead of classes.
  • PERSON[ id, name, ...]
  • ADDRESS[ id, person_id, city, street,...]

The person_id column in Address table is the relational information between thease two tables.
So, Address is an owner of the relationship, and Person is the inverse side.
"inverse=true" means "this side is the inverse side", and "inverse=false" means "this is not the inverse side. this side is the owner of the relationship".


Answer is:

<class name="Person">
<id name="id">...</id>
<set name="addresses" inverse="true">
<key column="person_id"/>
<one-to-many class="Address"/>
</set>
</class>


<class name="Address">
<id name="id">...</id>
<many-to-one name="person" class="Person" />
</class>



In sum, look at the table structure to distinguish "inverse=true" or "inverse=false".
If the table has relational information, then it is the owner side. So, it's not inverse side.(inverse=false)
If the table doesn't have relational information, then it is the inverse side. So, it needs "inverse=true".

19 comments:

Anonymous said...

Another way to look at it is by looking at the many end. In such cases the inverse=true goes on the end with the collection.

Anonymous said...

It's much simpler: If you map the same foreign key column twice, you need to "disable" one side by making it inverse. Which side varies.

If I have a one-to-many with a persistent List or Map, I'd make that side inverse="false" and the many-to-one should be disabled for updating/insertion with insert="false" and update="false".

If I have one-to-many with a persistent Set, I'd make that side inverse="true" and let the many-to-one update/insert the foreign key column.

If I have a many-to-many with a persistent Set on both sides, I can pick which side is "disabled", no difference.

If I have a many-to-many with a persistent List or Map on one of the sides, I need to enable that side and disable the other side (otherwise the index/map key of that list or map isn't stored.)

That's it.

Anonymous said...

Firstly, thanks for the great explanation. I have some question regarding one of the post though..I was hoping you would be able to explain it to me.

"If I have a one-to-many with a persistent List or Map, I'd make that side inverse="false" and the many-to-one should be disabled for updating/insertion with insert="false" and update="false"."

Why did he treat the "inverse" differently for "Set" & "List/Map" ?


Thanks again.

Prati said...

Thanks for great explanation.i have one query
Person aPerson = (Person) session3.load(Person.class, personId);
aPerson.getEvents().remove(aPerson);

Where events is a set
But i am not able to remove the corrosponding row,i can only remove row using Session.delete(aPerson)

Any Comments would be highly appreciated

Cheers
Pratibha

Nirmal said...

Check this for a complete understanding of inverse="true"
:)


http://simoes.org/docs/hibernate-2.1/155.html#A5

Gold Guide for World of Warcraft said...

good post :)

- said...

Thanks much!

Anonymous said...

Hello!!! tadtech.blogspot.com is one of the most outstanding innovative websites of its kind. I take advantage of reading it every day. All the best.

Anonymous said...

The author of tadtech.blogspot.com has written an excellent article. You have made your point and there is not much to argue about. It is like the following universal truth that you can not argue with: You cannot teach someone unless you are willing to learn from them. Thanks for the info.

Anonymous said...

Genial post and this enter helped me alot in my college assignement. Thanks you for your information.

Anonymous said...

Wow, thanks a lot!!! Finally I understood that!!!

Pooja said...

Great post!
Simple explanation for a seemingly difficult topic!

Anonymous said...

good explanation .. thank you

Peter said...

Excelent explanation, simple as water.

Ish Arora said...

excellent post

Anonymous said...

Good post. thanks!

Unknown said...

Thank u so much...

Anonymous said...

Thanks ..appreciated .. very much

Anonymous said...

PERFECT EXPLANATION .

Other guides make this concept way too damn confusing and you managed to simplify it in like 2 paragraphs.

Great Job