NHibernate and Inverse=True|False Attribute

In order to truly understand the inverse attribute in NHibernate, you need to first look at your relationship from the database table point of view and how your domain objects maps into their respective tables.  It comes down to determining who is the owner of the relationship association between the parent and child objects.

Suppose you have ParentTable (parentId PK, parentcol1, parentcol2) and ChildTable(childid PK, parentid FK, childcol1, childcol2).  In a one-to-many relationship, you will have one parent and many children.  The ChildTable has a primary key and foreign key.   The foreign key is a reference to the primary key in the ParentTable.  If you look at the ChildTable, you will notice that the ChildTable stores extra information about a row in the ParentTable via the ChildTable's parentId foreign key.  Using this perspective, the "child" owns (knows about) the relationship it has with its parent row.  So, the child will be the owner of the relationship in this one-to-many relationship.

Where does inverse come in?  Well, from the Parent's perspective, since the parent doesn't own the relationship it is considered the "inverse" of the relationship.  Below is some additional information I pulled down an edited from IBM's websphere pages:

http://www.ibm.com/developerworks/websphere/techjournal/0708_vines/0708_vines.html

Many-to-one relationship

The entity declaring the many-to-one relationship is the child object (or owner of the relationship), as its table has the foreign key, while the object that is referenced by the entity declaring the many-to-one relationship is the parent object. Since its table doesn't have the foreign key, it is the non-owner, or inverse of the relationship.

Hibernate conventions

In Hibernate, many-to-one relationship maps as follows:

  • Use many-to-one element in the child class.
  • Define the primary key in the parent class.

 

One-to-many relationship

A one-to-many relationship defines a reference to a collection of objects. It is the most common kind of relationship that you will find in object models due to the fact that use cases typically require traversal from the parent object to its children, but may or may not require traversal from the child back to its parent; which means a unidirectional one-to-many relationship will suffice in most cases.

The entity declaring the one-to-many relationship is the parent object (and is the non-owner). The table for this entity defines the primary key, but it does not have the foreign key -- that is in the child.

In Hibernate, the mapping of one-to-many relationships is generally done by adding a column to the child table for the foreign key, but the details of the mapping differs depending on whether it is a unidirectional or a bidirectional one-to-many relationship.

In the unidirectional case, the foreign key column in the child table doesn't map to a property in the child object; it is in the data model, but not the object model. Since it is unidirectional there is just a property in the parent object [that contains a collection of children]; not the child [the child object does not contain any information back to the parent]. In addition, the foreign key column [in the child table] has to be defined as nullable because Hibernate will first insert the child row (with a NULL foreign key) and then update it [the inserted row] later [with the parent's primary key].

In the bidirectional case, the object-relational mapping is better because there is a property in the child object for the foreign key column, and that column doesn't have to be nullable in the database. But the resulting object model has cyclic dependencies and tighter coupling between the objects, and requires additional programming to set both sides of the relationship.

As you can see, there are several tradeoffs to consider with regard to the definition of one-to-many relationships, but using unidirectional relationships is generally recommended unless there are use cases that indicate the need for navigation in both directions.

Hibernate conventions

In Hibernate, one-to-many (unidirectional) relationships map as follows:

  • Use the set, bag, or list with one-to-many sub-element in parent class.
  • Create a foreign key in the table representing the child class if the relationship is unidirectional; otherwise, use the many-to-one relationship for a bidirectional relationship.

There are some additional features that are often used in the definition of one-to-many relationships[...]:

  • Hibernate

    • inverse="true"
      In Hibernate, you might encounter the inverse="true" attribute being used in the definition of a bidirectional relationship. If so, don't worry, because this feature is equivalent to ... the non-owner of the relationship whose table doesn't have the foreign key. Similarly, the Hibernate inverse="false" attribute is equivalent to the ... owner of the relationship whose table has the foreign key.

      In general, these notions align, except for the case where someone defines a Hibernate mapping with inverse="true" set on the many-to-one side of a bidirectional relationship. If you find such a mapping, you should change it ..., as it is not a best practice in Hibernate and does not generate optimal SQL. For instance, if the many-to-one side is set to inverse="true" then every time you create a child, Hibernate will execute two SQL statements, one to create the child and one to update the child with the foreign key of the parent. Changing it to inverse="false" on the many-to-one side and setting inverse="true" on the one-to-many side will fix that oversight ...

 

Many-to-many relationship

A many-to-many relationship defines a reference to a collection of objects through a mapping table. Many-to-many relationships are not all that common in an object model, but they will generally be bidirectional.

Like the other bidirectional relationships, there is an owning and a non-owning side. In this case, the owning side has the mapping table, instead of the foreign key. Either side can be designated as the owning side; it doesn't matter which side you pick.

Hibernate conventions

In Hibernate, many-to-many relationship maps as follows:

  • The non-owner uses the collections (set, bag, or list) element with the inverse="true" attribute, the table attribute, the key sub-element, and the many-to-many sub-element.
  • The owner of the relationship uses the collections (set, bag, or list) element with the table attribute, the key sub-element, and the many-to-many sub-element.
20 Comments Filed Under [ NHibernate ]

Comments

# NHibernate and Inverse=True|False Attribute
Gravatar Bookmarked your post over at Blog Bookmarker.com!
Left by inverse on 1/7/2008 8:37 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Very nice article on Inverse attribute. It will be great, if you can post for the attribute "Cascade".
Left by Selva on 1/11/2008 12:42 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar This is so great! It's very helpful to me.
Left by gush on 2/17/2008 7:52 AM
# 
Gravatar NHibernate Inverse="true" Definition
Left by TipsOnLips.net on 7/16/2008 7:56 PM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Thanks, it solves my problem
Left by Stevey on 7/29/2008 10:08 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Great article! Thanks! :)
Left by sym on 11/28/2008 3:13 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar this is very usefull content for Freshers on Hibernate
Left by santharao chimili on 12/17/2008 10:48 PM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Great article.
Left by Anderson Lima on 12/23/2008 9:15 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Great article thank you
Left by Barbaros on 12/23/2008 4:50 PM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Thanks.

How do I get parents with childs only?
Left by Jake Kim on 1/21/2009 4:42 PM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Helped me!
Kudos! A confusing idea explained very clearly.
Left by Neal on 3/1/2009 4:09 PM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Very good article. I was confused how to use the mapping rules before, but now its clear. 5*
Left by Adam Price on 3/16/2009 11:49 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Great explanation! I hadn't clearly understood Inverse until now.
Left by Mark Hoffman on 3/28/2009 9:42 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Great article,

Hello,

I would like to take to this opportunity to ask a question about one-to-many. I ahve two classes:

GeneralInformation and famousPlacesInLondon

public class GeneralInformation
{

private int id;

public virtual int Id
{
get { return id; }
set { id = value; }
}

private IList<FamousPlacesInLondon> famousPlacesOutLondon;

public virtual IList<FamousPlacesInLondon> FamousPlacesOutLondon
{
get { return famousPlacesOutLondon; }
set { famousPlacesOutLondon = value; }
}
}

public class FamousPlacesInLondon
{
private int id;

public virtual int Id
{
get { return id; }
set { id = value; }
}
private string link;

public virtual string Link
{
get { return link; }
set { link = value; }
}
private string title;

public virtual string Title
{
get { return title; }
set { title = value; }
}

}
}

My mapping are as follows:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model" namespace="Model">
<class name="Model.GeneralInformation,Model" table="GeneralInformation">
<id name="Id">
<generator class="native" />
</id>
<bag name="FamousPlacesInLondon" table="FamousPlacesInLondon" cascade="all">
<key column="GeneralInformationId" />
<one-to-many class="Model.FamousPlacesInLondon,Model"/>
</bag>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model" namespace="Model" >
<class name="Model.FamousPlacesInLondon,Model" table="FamousPlacesInLondon" >
<id name="Id">
<generator class="identity" />
</id>
<property name="Link" column="Link" type="string" />
<property name="Title" column="Title" type="string" />
</class>
</hibernate-mapping>

If I fill the GeneralInformation with data and do a save using NHibernate, everything gets inserted into the appropriate table, except the ForeignKey GeneralInformationId. What is wrong?

TIA
Yaz
Left by Yazid on 4/23/2009 4:26 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar make sure that the id name in the key column matches the id name in the "GeneralInformation" mapping.
Left by SunilGujja on 5/4/2009 5:37 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Excellent post and helped me get my head round a relatively simple concept that can be quite difficult to understand.

One suggestion though... it would have been easier to understand if you'd used a real-world example like Blog and BlogPosts rather than parent and child. So in this case the Blog would have a collection of blog posts which would be inverse because the relationship is actually referenced from the blogpost table right?

Thanks again! you helped me a lot!
Left by Kevin on 5/16/2009 5:51 AM
# NHibernate
Gravatar NHibernate
Left by Un po' di spazio per Theswra... on 5/25/2009 8:18 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar gr8 post
Left by Ajay on 6/21/2009 7:46 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Thank you very much for the explanation
Left by Xavier on 10/26/2009 3:47 AM
# re: NHibernate and Inverse=True|False Attribute
Gravatar Really nice explanation, thanks for hard work!
Left by gby on 11/30/2012 3:58 AM

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 5 and 1 and type the answer here:

Preview Your Comment.