So far we have been using the term entity to refer to classes that NHibernate is able to persist to database. But when it comes to NHibernate, there is more to that term. An entity is something that has its own identifier and can be distinguished from another instance of same type by using the identifier value. An important feature of entity is that NHibernate is able to track the entity. This means that NHibernate knows whether the entity is only present in memory but is not persisted to database, or is persisted to database but the instance in the memory is updated, and so on (sometimes this is also called dirty tracking). Another important feature of entities is that they are saved in their own database table. The way NHibernate handles the entities gives them an identity of their own. This enables the entities to be fetched from database, navigate from one entity to other entity, and so on, using entity identifiers.
Not every class in the domain model needs to be an entity. For instance, the Address
class from our domain model does not need to have its own identifier, and properties of this class can be persisted in Employee
table itself. In such case, the Address
class can be mapped as a component. But mapping a class as a component puts some restrictions on it, as listed next:
Mapping components is very simple. Mappings for component
are declared inside the mappings of the class that references the component. You can declare the component
mapping using XML node component
as the following code snippet shows. Properties on the component
class are mapped as properties on any other class:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Component"> <class name="Employee"> <id name="Id" generator="hilo" /> <property name="EmployeeNumber" length="10" /> <property name="Firstname" /> <property name="Lastname" /> <property name="EmailAddress" /> <property name="DateOfBirth" /> <property name="DateOfJoining" /> <property name="IsAdmin" /> <property name="Password" /> <component name="ResidentialAddress" class="Address"> <property name="AddressLine1"/> <property name="AddressLine2" /> <property name="Postcode" /> <property name="City" /> <property name="Country" /> </component> </class> </hibernate-mapping>
In the previous code sample, additional mappings of other properties on the Employee
class are depicted to show you how component fits in the overall picture. Component mapping needs the name
and class
attributes to be specified. In the name
attribute, declare the name of the property on the entity which is referring to the component
class. In the class
attribute, specify the type of the component
class. Properties of the component
class are mapped like any other properties.
The unit test we used previously to test mappings for the Address
class cannot be used as is when Address
is mapped as component. This is mainly because now the Address
class does not have reference back to Employee
and hence test needs to be written considering this in mind. I have omitted the refactored test here but you can find it in the source code of the book.
NHibernate's support for components is quite elaborate. What we have covered is the most common configuration of components. As beginners to NHibernate, the preceding should suffice you to move along. But if you are interested in learning different aspects of component support in NHibernate, then you may wish to head over to the official documentation at http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-component.
With this we can conclude our discussion of XML mappings. We have covered most important aspects of XML mappings but there is a lot more to be learned. We will continue learning something new about mappings in every chapter of this book. For the moment, let's jump into the second mechanism of mapping offered by NH.