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:"
And what we want is to map this to the following object model:
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:
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.

Comments
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 :).
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.
Evgeny,
I don't see the typo
Jan,
Yes, that is what I meant.
Great series of posts.
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
tolly,
Please follow this up in the mailing list
Thanks, Ayende :) Hopely, I'll find the way.
It's a greate blog, i've learnt a lot of new things about NHibernate, thanks
Guys,
We're trying to use the
<join 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
<join 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.
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.
Comment preview