views:

255

answers:

2

Let's say that I have a class/table called Images that, as it stands right now, is bound in a manner similar to this:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Domain.Image, Domain" table="Images">
    <id name="id" column="ImageID" access="field" unsaved-value="0">
      <generator class="identity" />
    </id>    
<!-- other properties -->
    <property name="AssociatedObjectID" column="AssociatedObjectID" />
    <property name="AssociatedObjectType" column="AssociatedObjectType" />
  </class>
</hibernate-mapping>

Up until this point, this schema has worked, because a image was only associated with one object, so I could keep that reference without a discriminator.

However, now I wish to have a collection of these images on another entity called a PhotoShoot. Each PhotoShoot can have several images.

Is there a way to bind a collection such that I can have a List<Image> within PhotoShoot without extracting a base class and using the table-per-hierarchy inheritance pattern?

And if not, is table-per-hierarchy really the best way to go here? I hate to create subclasses, especially since there is nothing that needs to be abstracted from the Image entity.

A: 

You could use a many-to-many mapping tables, rather than putting the AssociatedObjectId/Type in your image class/table. Many-to-manys are a little trickier to work with in Hibernate, but give you some extra flexibility.

Image
-----
Id (PK)
OtherProp1
OtherProp2

Attachment
----------
Id (PK)
OtherProp1

AttachmentImage (many-to-many between Attachment and Images)
---------------
ImageId (PK, FK to Image.Id)
AttachmentId (PK, FK to Image.Id)

PhotoShoot
----------
Id (PK)
OtherProp1
-- AttachmentId (if PhotoShoot has only a single attachment)

PhotoShootAttachment (if Photoshoot can have many attachments)
--------------------
ImageId (PK, FK to Image.Id)
AttachmentId (PK, FK to Attachment.Id)
Andy White
+1  A: 

I would map this as an IList<Images> property on PhotoShoot, mapped via a join table (many-to-many).

If the ordering of the list is important, map as a list otherwise as a bag. I have included both mappings.

<class name="Domain.PhotoShoot, Domain" table="PhotoShoot">
    <id name="id" column="PhotoShootId" access="field" unsaved-value="0">
      <generator class="identity" />
    </id>    
    <!-- other properties -->

    <!-- unordered list -->
    <bag name="Images" table="PhotoShoot_Image" fetch="join" cascade="all-delete-orphan">
        <key column="PhotoShootId"/>
        <many-to-many class="Domain.Image, Domain" column="ImageId" />
    </bag>

    <!-- ordered list -->
    <list name="Images" table="PhotoShoot_Image" fetch="join" cascade="all-delete-orphan">
        <key column="PhotoShootId"/>
        <imdex column="position" />
        <many-to-many class="Domain.Image, Domain" column="ImageId" />
    </list>
</class>

public class PhotoShoot
{
    IList<Image> Images { get; set; }
}

Using @ddango's original class mapping we could instead do the following.

<class name="Domain.PhotoShoot, Domain" table="PhotoShoot">
    <bag name="Images" table="Image" fetch="join" where="AssociatedObjectType='PhotoShoot'">
        <key column="AssociatedObjectId"/>
        <one-to-many class="Domain.Image, Domain" />
    </bag>
</class>
Lachlan Roche
This is what I'm looking to do, except in this case the key column is a combination of AssociatedObjectId = PhotoShootId and AssociatedObjectType = 'PhotoShoot'. It would be possible that the AssociatedObjectId is the same for another Image, so I would pull Images that I do not want.
ddango