NHibernate Mapping - <join/>

We have previously explored the one-to-one mapping, which let you create 1:1 association in the database, but there is actually another way to map several tables to an object model. We aren’t constrained by the database model, and we can merge several tables into a single entity.

We do that using the <join/> element:

<join
        table="tablename"                        (1)
        schema="owner"                           (2)
        catalog="catalog"                        (3)
        fetch="join|select"                      (4)
        inverse="true|false"                     (5)
        optional="true|false">                   (6)

        <key ... />

        <property ... />
        ...
</join>

Let us explore this a bit, assuming the we have the following database model:"

image

And what we want is to map this to the following object model:

image

We can do this will the following mapping:

<class name="Person"
	 table="People">

	<id name="Id">
		<generator class="identity"/>
	</id>
	<property name="Name" />

	<join table="Addresses">
		<key column="PersonId"/>
		<property name="Line1"/>
		<property name="Line2"/>
		<property name="City"/>
		<property name="Country"/>
		<property name="ZipCode"/>
	</join>
</class>

And getting a Person will now result in the following SQL:

image

NHibernate will now take care of mapping everything to its place, and making sure that everything works just right.

By now you should be able to figure out what fetch means, and inverse should also be familiar. Optional is interesting, what is basically says is that we should always use an outer join to get the values from the Addresses table and if all the mapped properties are null, it wouldn’t create a new row in the Addresses table.

On the face of it, it looks like a nice way to merge tables together, but that isn’t actually the primary reason for this feature. You can use it for that, for sure, but that is mostly useful in legacy databases. In most cases, your object model should be more granular than the database model, not the other way around.

The really interesting part about this feature is that it allows us to mix & match inheritance strategies. It let us create a table per hierarchy that store all the extra fields on another table, for example. That significantly reduce the disadvantage of using a table per hierarchy or table per subclass, since we can tell very easily what is the type of the class that we are using, and act appropriately.

Print | posted on Monday, April 20, 2009 3:56 AM

Feedback


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 6:00 AM Evgeny Shapiro

It let us create a =table per hierarchy= that store all the extra fields on another table, for example. That significantly reduce the disadvantage of using a =table per hierarchy= or table per subclass...

There's a typo.

Beside this, the post series is awesome :).


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 10:49 AM Jan Van Ryswyck

The mix & match inheritance strategy you mentioned, is it something like this?

knol.google.com/.../11#8(2E)1(2E)3(2E)(C2)(A0)Table_per_subclass(2C)_using_a_discriminator

Thx

PS: I'm learning a lot from this article series. Thx for spreading the knowledge.


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 11:10 AM Ayende Rahien

Evgeny,
I don't see the typo


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 11:16 AM Ayende Rahien

Jan,
Yes, that is what I meant.


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 11:50 AM Remmus

Great series of posts.


Gravatar

# re: NHibernate Mapping - <join/> 4/20/2009 5:30 PM tolly

In the post about {dynamic-component/} i've asked about the way to store key-value pair in detail-table. ayende.com/.../...pping-ltdynamic-componentgt.aspx

I'd like to solve inhertance problem using this key-value princniple. see picture: tweakers.net/.../full.jpg

I want that NHibernate dynamically creates subclasses' attributes using detail-table with key-value pair, where key is the name of the attribute and the value is the value.
Is it possible with NHibernate?

I prefer this solution over the standard ones (like table-per-subclas or table-per-concrete-class), because i have more than 80 subclasses with three hierarchical levels and all with their specific attributes.

Thanks in advance


Gravatar

# re: NHibernate Mapping - <join/> 4/21/2009 10:38 AM Ayende Rahien

tolly,
Please follow this up in the mailing list


Gravatar

# re: NHibernate Mapping - <join/> 4/21/2009 11:26 AM tolly

Thanks, Ayende :) Hopely, I'll find the way.

It's a greate blog, i've learnt a lot of new things about NHibernate, thanks


Gravatar

# re: NHibernate Mapping - <join/> 4/30/2009 5:26 PM scotty

Guys,

We're trying to use the condition in a table that has a composite primary key. Outwith the composite key in that table we have another field which is used as a foreign key onto a lookup table.

Nhibernate complains with the classic 'Foreign key does not have the same number of columns as primary key...' error, when using the onto the lookup table.

We've even taken off the foreign key and tried this, but it looks like Nhibernate is dynamically creating a foreign key at runtime, and throwing the error.

All we're doing is effectively an inner join onto a lookup table, from a table with a composite primary key.

Any ideas?

We know creating a surrogate key will solve this, but we're loathe to go down that route.

thanks.


Gravatar

# re: NHibernate Mapping - <join/> 4/30/2009 7:25 PM Ayende Rahien

Scotty,
NH isn't trying to generate the FK on the fly, it is complaining because you have an invalid definition. You must have the same number of columns on both.

Comments have been closed on this topic.