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.