There are three different approaches to represent a class inheritance hierarchy.
1) Table per concrete class
This approach uses one table for each (non-abstract) class. All class properties, including inherited properties, can be mapped to columns in the table.
In NHibernate, use a <class> declaration for each concrete class, specifying a different table attribute for each.
Problems with this approach:
2) Table per class hierarchy
An entire class hierarchy is mapped to a single table. The table includes columns for all properties of all classes in the hierarchy.
This strategy is both simple and good for performance.
The concrete subclass represented by a particular row must be identified by a unique value (a type discriminator column).
In NHibernate, use the <subclass> element to define this class hierarchy mapping for each subclass and map the base class using a <subclass> element. Specify, the unique row identifier column using the <discriminator> element in the base class mapping and discriminator attribute in the subclass mapping.
Problems with this approach:
3) Table per subclass
Every subclass that declares persistent properties (including abstract classes and even interfaces) has its own table.
The table here contains columns only for each non-inherited property (each property declared by the subclass) along with a primary key that is also a foreign key of the base class table. The two rows are linked together by their shared primary key value.
In NHibernate, you use the <joined-subclass> element to indicate a table per subclass mapping. NHibernate will then use an outer join when querying the database.
Advantages of this approach:
Associations refer to relationships between entities, and are mainly unidirectional.
One-to-many associations are the most important and popular type.
Many-to-many associations can be represented as two many-to-one associations. To represent a many-to-one relationship, need to definite two associations. One association mapping the many-to-one side of the relationship, and the other mapping representing the one-to-many side of the relationship.
One-to-one association
There are two different ways to represent one-to-one associations:
Many-to-many association
Use an intermediate association class to represent a many-to-many relationship.
For unidirectional many-to-many relationships:
For bidirectional many-to-many associations:
One-to-many association
Used to map a typical parent/child relationship between two entity persistent classes using a <one-to-many> and a <many-to-one> mapping.
Use a <set> collection mappings for typical parent/child relationships.
You can use four different approaches to represent a collection.
Using a Set
Using a Bag
Using a List
Using a Map
NHibernate lets you specify a default fetching strategy in the XML mapping file, with the ability to then override it at runtime in code.
NHibernate provides four different fetching strategies for any assocation: Immediate, Lazy, Eager or Batch.
Immediate Fetching
Lazy Fetching
Eager Fetching
Batch Fetching
The fetching strategy can be overwritten for a particular association using the outer-join attribute for an association, as follows:
For single point associations
| Property Attribute | Attribute Description |
|---|---|
| outer-join="auto" | Default. Dependant on fetching strategy specified for the class. If class is configured for lazy fetching than NHibernate fetches the association lazily, otherwise NHibernate fetches the association eagerly. |
| outer-join="true" | NHibernate fetches the association eagerly using an outer-join, even if the class has been configured for lazy fetching. |
| outer-join="false" | NHibernate never fetches the association using an outer join, even when lazy fetching is disabled. |
For collections
| Property Attribute | Attribute Description |
|---|---|
| outer-join="true" | NHibernate fetches the collection eagerly using an outer join. |
| lazy="true" | NHibernate fetches the collection lazily, when it is first accessed. This option is preferred for collection mappings, and is the default in HNibernate 2.1. |
The correct fetching strategy minimizes the number of SQL statements that have to be executed by lazily, eagerly, or batch-fetching objects.