Angel \”Java\” Lopez on Blog

April 11, 2011

NHibernate 3 (Part 3) Table Per Concrete Class

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

Previous post
Next post

I want to use the same domain from the previous post:

 

but this time, I want two tables: one for Notes, another for Pages:

The solution has two projects: a class library containing the domain, and the console project:

The code is at my AjCodeKatas Google code project, under trunk/NHibernate/ItemsTablePerConcreteClass. The code doesn’t include the NHibernate libraries, so you must add the references to the solution. As in the previous example, I added as reference to console project: NHibernate.dll from the NHibernate folder Required_Bins and NHibernate.ByteCode.Castle from Required_For_LazyLoading\Castle. I added the .xsd files (XML schemas to support intellisense when writing the mapping files) from NHibernate folde Required_Bins.

You can download the source code directly from NHibernate3ItemsTablePerConcreteClass.zip. If you need the NHibernate 3.x libraries, check http://nhforge.org or download my first example NHibernate3SimpleMapping.zip, that includes them. Check my first post to review: libraries to add, schemas, configuration file, and mapping files (don’t forget to add as embedded resources).

Note that the domain classes are the same: they don’t change from the previous example. I changed the mapping files, not the code. This is a proof of domain independence of our mapping strategy.

First, the Item.hbm.xml:

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

First, I removed the discriminator column. There is no such column, because there is no Items table. I added the attribute abstract=”true”. If you forget to add it, then NHibernate “thinks” you have a concrete table for this class. You can remove it, if you have concrete Items that are not Notes, Pages. This is not the case I want to implement: the only “real” items are Notes or Pages. Item is an abstraction in my domain.

The Note.hbm.xml:

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

I added the attribute table=”Notes”. And the new element is union-subclass, instead of subclass as in previous example. This new element is the way to say: “the table of this class CONTAINS the columns to save the parent class values”. That is: the table columns are the UNION of the parent class and this class values.

Similar changes for Page.hbm.xml:

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

The main code is practical the same from the previous example:

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);
        var items = session.Query<Item>(); ;
        foreach (Item item in items)
            System.Console.WriteLine(string.Format("Item {0}", item.Title));
        tx.Commit();
        session.Close();
    }
}

except that this time, I began to use Session.Query<T>, a new extension method for NHibernate sessions, that returns a IQueryable<T> implementing Linq. You MUST add:

using NHibernate.Linq;

to have this method. It is an extension method, not a “natural one” for ISession.

My sources of information:

Book: Jason Dentler’s NHibernate 3.0 Cookbook

http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-unionsubclass

http://www.nhforge.org/doc/nh/en/index.html#inheritance

Next steps: implement Table per Class strategy, explore one-to-many, lazy collections, etc.Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

3 Comments »

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

    Pingback by NHibernate 3 (Part 2) Table per Hierarchy « Angel “Java” Lopez on Blog — April 11, 2011 @ 9:52 am

  2. […] 3 (Part 4) Table Per Class Filed under: .NET, C Sharp, NHibernate — ajlopez @ 10:50 am Previous post Next […]

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

  3. Somebody essentially lend a hand to make critically posts
    I might state. This is the first time I frequented your
    web page and up to now? I surprised with the research you made to create this actual post incredible.

    Magnificent activity!

    Comment by mick mars — May 3, 2013 @ 6:24 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

Create a free website or blog at WordPress.com.

%d bloggers like this: