Angel \”Java\” Lopez on Blog

April 5, 2011

NHibernate 3 (Part 2) Table per Hierarchy

Filed under: .NET, C Sharp, NHibernate — ajlopez @ 9:18 am

Previous post
Next post

In the previous post of this series, I implemented a simple mapping: one class, one table.

But now, I have three classes, with inheritance:

The Id is a System.Guid. I want to have an item collection. Each item can be a Note, with text content, or a web Page, with an associated URL. The solution has two projects:

I keep the source code at my AjCodeKatas Google code project, under trunk/NHibernate/ItemsTablePerHierarchyMapping. The code doesn’t include the NHibernate libraries, so you must add the references to the solution. I added as reference to console project: NHibernate.dll from the NHibernate folder Required_Bins and NHibernate.ByteCode.Castle from Required_For_LazyLoading\Castle.

If you are lazy, like me, and you want a ready-to-build solution, you can download the previous example with NHibernate required files from my Skydrive: NHibernate3SimpleMapping.zip. The code of this post is at: NHibernate3ItemsTablePerHierarchy.zip.

The Domain project has no reference to NHibernate. All the mappings are in the Console project, as embedded resource (don’t forget this).

I have 3 classes to map. But I want to store all data in only one table:

You can generate the database executing ExecuteAll.cmd in Sql directory.

The table Items has a column ItemType, that mark an item as a Note or as a Page. The Item.hbm.xml reference that column as a discriminator:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <class name="Item" table="Items">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <discriminator column="ItemType" />
    <property name="Title" not-null="true" />
    <property name="Description" not-null="true" />
  </class>
</hibernate-mapping>

Note that I have no such property in the classes: the discriminator is only used by NHibernate.

Now, I need to map Note objects. How to write the mapping? This is Note.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <subclass name="Note" extends="Item" discriminator-value="Note">
    <property name="Content" />
  </subclass>
</hibernate-mapping>

The new XML element is subclass. It has an extends attribute that reference to the parent class. The discriminator-value attribute has the value to put in the discriminator column when the Item is a Note. If you don’t specify the discriminator value, the name of the class would be used, in this case ItemsTablePerHierarchyMappin.Domain.Note.

The Page.hbm.xml is similar:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <subclass name="Page" extends="Item" discriminator-value="Page">
    <property name="Url"/>
  </subclass>
</hibernate-mapping>

You can run the console code:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Page page1 = new Page();
        page1.Title = "Technical Blob";
        page1.Description = "My Personal Technical Blob in English";
        page1.Url = "https://ajlopez.wordpress.com";
        Page page2 = new Page();
        page2.Title = "My Personal Blob";
        page2.Description = "My Personal Blob in Spanish";
        page2.Url = "http://ajlopez.zoomblog.com";
        Note note1 = new Note();
        note1.Title = "To Do";
        note1.Description = "My To Do List";
        note1.Content = "Practice NHibernate";
        session.Save(page1);
        session.Save(page2);
        session.Save(note1);
        IQuery query = session.CreateQuery("from Item");
        foreach (Item item in query.List<Item>())
			System.Console.WriteLine(string.Format("Item {0}", item.Title));
        tx.Commit();
        session.Close();
    }
}
System.Console.ReadKey();

to insert and list items.

This mapping strategy (the old trick of saving every subclass in a single table, using discriminators 😉 is called Table Per Hierarchy (Fowler names it Single Table Inheritance).

Next steps: implement other mapping strategies: one table per concrete class (in this case, Pages and Notes); one table per class (Items, Pages, Notes).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

10 Comments »

  1. […] Previous post of this series Next post of this series […]

    Pingback by NHibernate 3 (Part 3) Table Per Concrete Class « Angel “Java” Lopez on Blog — April 11, 2011 @ 9:49 am

  2. […] 3) Table Per Concrete Class Filed under: .NET, C Sharp, NHibernate — ajlopez @ 9:49 am Previous post of this series Next post of this […]

    Pingback by NHibernate 3 (Part 3) Table Per Concrete Class « Angel “Java” Lopez on Blog — April 11, 2011 @ 9:50 am

  3. […] Next post […]

    Pingback by NHibernate 3 (Part 1) Simple Mapping « Angel “Java” Lopez on Blog — April 11, 2011 @ 9:55 am

  4. […] the previous posts (Table per Hierarchy, Table Per Concrete Class), I implemented two mapping strategies for the same […]

    Pingback by NHibernate 3 (Part 4) Table Per Class « Angel “Java” Lopez on Blog — April 12, 2011 @ 10:51 am

  5. Good answers in return of this issue with solid arguments and explaining everything concerning that.

    Comment by Jada — May 2, 2013 @ 5:50 am

  6. In getting the best wireless routers, it is imperative that
    anyone should ascertain first what kind of user they are.
    If your partner is stressed, or depressed, or
    sick, your body will have a very difficult time achieving a
    state of full relaxation and restfulness. s better to prevent putting the wireless access points or wireless Routers near such devices and better
    to choose frequency bands which are different than the ones used by the cordless telephone, also the Wireless Networks affected by some kind of materials such as foils, hence all of the mentioned devices and materials would make an
    attenuation to the Wireless Networking signals and will reduce or might block the signal.

    Comment by Marti — May 7, 2013 @ 5:27 pm

  7. Article Source: part is important, so read carefully.
    Such tattoos bear positive meaning and are widely spread in
    Britain and Europe. For dragon lovers, looking for that perfect
    dragon figure as a gift can be a daunting and puzzling mission.

    Comment by Facebook Game — May 10, 2013 @ 3:39 pm

  8. In it’s first seven days, 6 million units were sold beating last year’s sales figures for Halo 3.

    Grand Theft Auto IV was expected to push sales of the Xbox 360
    and the Playstation 3 for which it was designed, and these consoles as if you didn’t know, are in stiff competition with the increasingly popular Nintendo Wii. The video game seems to be fantastic, sounds great and takes on very efficiently.

    Comment by Benny — May 13, 2013 @ 12:41 pm

  9. The process of car shopping can be lengthy. You
    have so many options, not to mention things to consider as you
    compare each one. You will be able to make the
    right decision if you know enough about car shopping. Here are some great tips
    on buying a car.

    Comment by cars — June 16, 2013 @ 11:33 pm

  10. Thanks for sharing your thoughts about gay porn.
    Regards

    Comment by Erin — August 3, 2013 @ 1:07 am


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

Blog at WordPress.com.

%d bloggers like this: