Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate: Why would you use <composite-element> over <one-to-many> to map a collection

When using NHibernate, under what circumstances would you choose to map a collection using a composite-element to give a collection of value objects, rather than creating a full-blown entity and mapping it using one-to-many?

You might have a value-type class 'PostalAddress' to represent an address. If you had a person entity and each person could have many addresses you could map this relationship like this (Option 1):

<bag name="Addresses" table="PersonAddress">
    <key column="PersonID"/>
    <composite-element class="PostalAddress">
        <property name="StreetAddress"/>
        <property name="Town"/>
        <property name="City"/>
        <property name="Postcode"/>
    </composite-element>
</bag>

Or you could create an entity 'PersonAddress' which has a 'PostalAddress' typed property on it and map the addresses with a one-to-many association (Option 2):

<bag name="Addresses">
    <key column="PersonID"/>
    <one-to-many class="PersonAddress"/>
</bag>

<class name="PersonAddress">

    <id name="Id">
        <generator class="native"/>
    </id>

    <component name="Address" class="PostalAddress">
        <property name="StreetAddress"/>
        <property name="Town"/>
        <property name="City"/>
        <property name="Postcode"/>
    </component>

</class>

Are there any reasons not to do option 1? Does the fact that the PersonAddress table has an ID column suggest that it should be an entity itself, hence use option 2?

like image 866
Matthew Winder Avatar asked Nov 30 '10 13:11

Matthew Winder


1 Answers

<composite-element> is for when you have a collection of values whereas <one-to-many> is a collection of entities. The defining characteristic of an entity is a unique identifier. So if the items in your collection have a PK, use <one-to-many>. Otherwise use <composite-element>.

Another way to think about it is how you determine equality. Do you determine equality by comparing an ID or by verifying that all properties are identical? e.g. In your application, do two objects represent the same address if (address1.Id == address2.Id) or if (address1.Street == address2.Street && address1.City == address2.City && etc.)? There is no universal right answer as it depends on application context. In many cases, money is a value object. Whether you have this $20 or that $20, it doesn't matter. Only the amount is relevant. If you were writing a tracking application for a mint, they probably need to know which $20 bill you're dealing with and you would track the serial number on the $20 bill. In this case, money is an entity. It all depends on application and context...

like image 165
James Kovacs Avatar answered Nov 09 '22 02:11

James Kovacs