Five ‘s Weblog

October 18, 2007

uni-directional or bidirectional ?

Filed under: ORM — by powerdream5 @ 10:52 pm
Tags: , , , ,

        When mapping the domain model to the database schema,  perhaps we often ask ourselves one question: Making a one-to-many relationship uni-directional or making it bidirectional, which is better in performance. Today, I am going to show an example to demonstrate the difference between uni-direction and bidirection. I am using Hibernate framework.

        There is a class named Consumer and a class named CreditAccount, both of which mapped to the consumer and credit_account table respectively. It is obvious that each Consumer has more than one credit account, therefore, the relationship between the two classes is one-to-many. Firstly, I make the relationship uni-directional.

10_18_2_2007.jpg 

the mapping files are listed in the following:

//Consumer.hbm.xml
<hibernate-mapping>
          <class name=”Consumer” table=”consumer”>
                 <id name=”id” column=”CONSUMER_ID”>
                       <generator class=”native” />
                </id>
               <property name=”firstName” type=”string” column=”FIRSTNAME”/>
               <property name=”lastName” type=”string” column=”LASTNAME”/>
               <set name=”creditAccount” table=”credit_account” cascade=”all”>
                      <key column=”CONSUMER_ID”/>
                      <one-to-many class=”CreditAccount” />
              </set>
           </class>
</hibernate-mapping>

//CreditAccount.hbm.xml
<hibernate-mapping>
          <class name=”CreditAccount” table=”credit_account”>
                 <id name=”id” column=”ACCOUNT_ID”>
                         <generator class=”native” />
                 </id>
                 <property name=”accountNumber” type=”string” column=”ACCOUNT_NUMBER”/>
          </class>
</hibernate-mapping>

We try to insert an new account into the database, from the comman window or log files, we can see that two sql setences are executed. There are:
insert into credit_account(ACCOUNT_NUMBER) values(?)
update credit_account set CONSUMER_ID=? where ACCOUNT_ID=?

Now, I am going to make a little change to the CreditAccount class to make the relationship between Consumer and it bidirectional.  Therefore, I also need to change the mapping files. After being changed, they should be:

//Consumer.hbm.xml
<hibernate-mapping>
          <class name=”Consumer” table=”consumer”>
                 <id name=”id” column=”CONSUMER_ID”>
                       <generator class=”native” />
                </id>
               <property name=”firstName” type=”string” column=”FIRSTNAME”/>
               <property name=”lastName” type=”string” column=”LASTNAME”/>

               //make sure to set “inverse=true”
               <set name=”creditAccount” table=”credit_account” cascade=”all” inverse=”true”>
                      <key column=”CONSUMER_ID”/>
                      <one-to-many class=”CreditAccount” />
              </set>
           </class>
</hibernate-mapping>

//CreditAccount.hbm.xml
<hibernate-mapping>
          <class name=”CreditAccount” table=”credit_account”>
                 <id name=”id” column=”ACCOUNT_ID”>
                         <generator class=”native” />
                 </id>
                 <property name=”accountNumber” type=”string” column=”ACCOUNT_NUMBER”/>
                 <many-to-one name=”consumer” class=”Consumer” column=”CONSUMER_ID”>
          </class>
</hibernate-mapping>

Now, if we insert a new account into the database, only one sql sentence will be executed:
insert into credit_account(ACCOUNT_NUMBER,CONSUMER_ID) values(?, ?)

       There is no doubt that bidirection is better than uni-direction in the performance. If the relationship is uni-direction, only one end is going to maintain their relationshop. The other end cannot see any change of the relationship.  Therefore, the first time we need to execute two sql sentences, the first sql sentence inserts the data into the credit_account table (at this time, the system doesn’t know this account belongs to whom), and the second sql help the credit_account table build its relationship with the consumer table. However, both the end of the bidirectional relationship are aware of any changes, therefore, only one sql sentence can finish two tasks: inserting data and mataining the relationship.

        You can download the source files.

10_18_1_2007.jpg

Advertisements

10 Comments »

  1. […] restst wrote an interesting post today onHere’s a quick excerpt . We try to insert an new account into the database, from the comman window or log files, … […]

    Pingback by domain registration » uni-directional or bidirectional ? — October 24, 2007 @ 12:59 am |Reply

  2. Excellent explanation. Thanks a lot!

    Comment by Kausik Ghatak — May 14, 2009 @ 3:48 pm |Reply

  3. really great explanation in simplest language and simplest way.

    Comment by Surendra Gautam — August 17, 2009 @ 7:15 am |Reply

  4. Both account and member is the prime entity, bidirectional relation will not only bring the advantage when create new entity but also many other operations e.g. view, update or delete etc.

    The photo is awesome! The lady is as nice as your beautiful explanation! Good job.

    Comment by Leee — September 30, 2009 @ 9:47 am |Reply

  5. Great explanation.

    Comment by Arvind — November 13, 2009 @ 9:15 am |Reply

  6. thanks for Awesome explaination.

    Comment by Amar — June 10, 2011 @ 10:57 am |Reply

  7. Simple and clear explenation…….:)

    Comment by Balaji — August 17, 2011 @ 7:09 am |Reply

  8. But maybe it does not make sense from the model point of view for the relationship to be bidirectional….

    E.g. if the “many” side is Category. Why should category maintain a collection of all the thousands of items that belong to that category? I only care for “item” to know which category it belongs to.

    Also, while I understand that in the case of a uni-directional relationship we will get 2 SQL queries, this is just the specific implementation of Hibernate. There’s no reason why you cannot do it in one query even in the uni-directional case. It’s more of a weird feature/bug that should be corrected.

    Comment by rapt — October 27, 2011 @ 9:00 am |Reply

  9. its pathetic…that query is changes because of inverse=true..which is by default inverse=false..

    Comment by k2 — August 10, 2012 @ 11:50 am |Reply

  10. Excellent goods from you, man. I’ve understand your stuff previous to and you are just too wonderful. I really like what you have acquired here, certainly like what you’re stating and the way in which you say it.
    You make it enjoyable and you still take care of to keep it
    smart. I cant wait to read far more from you. This is really a tremendous web site.

    Comment by How To Get Facebook Credits — July 22, 2013 @ 11:06 pm |Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: