-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: one-to-many with three tables
PostPosted: Thu Jun 16, 2005 9:04 am 
Hi,

Sorry for the 2nd question in as many days - I tried searching here and Hibernate but couldn't find what I need.

Anyway I have an object invoice which can have invoice items. Now the invoice items can come from either of two tables. I tried to setup the one-to-many in the mapping file but its not allowed the two ways I tried it. Heres what I have:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <class name="LogisticsManagement.Core.Components.Invoice, Logistics" table="Invoices">
    <!-- chopped bits out here -->
    <bag name="InvoiceItems" cascade="all" lazy="true">
      <key column="invoiceID" />
      <one-to-many class="LogisticsManagement.Core.Components.Vehicle, Logistics" />
    </bag>
    <bag name="InvoiceItems" cascade="all" lazy="true">
      <key column="invoiceID" />
      <one-to-many class="LogisticsManagement.Core.Components.TextJob, Logistics" />
    </bag>
    <!-- chopped bits out here -->
  </class>
</hibernate-mapping>


I also tried with just one bag element and two one-to-many tags within it which doesn't work either. Is this possible?

I've also done a bit of work creating a class hierarchy with an interface InvoiceableItem which the two classes TextJob and Vehicle derived from but that got complex very quickly. I'd rather keep the database tables separate as these are components of a system which I do not want too highly coupled.

The other option I thought of is to split Invoice into two almost identical classes so that the one-to-many will work in each case but duplication is bad so they tell me.

Any ideas for the design of this?

Many thanks.

Steve


Top
  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 9:55 am 
Newbie

Joined: Wed Jun 15, 2005 11:09 am
Posts: 10
Location: Salem, MA
Hopefully someone with some nHibernate experience will chime in, but I think the easiest approach might be to create your Invoice object with a single InvoiceableItems collection. That collection would be created from 2 internal collections of Vehicles and TextJobs. Vehicle and TextJob classes would each implement the InvoiceableItem interface:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <class name="LogisticsManagement.Core.Components.Invoice, Logistics" table="Invoices">
    <!-- chopped bits out here -->
    <bag name="InvoiceVehicles" cascade="all" lazy="true">
      <key column="invoiceID" />
      <one-to-many class="LogisticsManagement.Core.Components.Vehicle, Logistics" />
    </bag>
    <bag name="InvoiceTextJobs" cascade="all" lazy="true">
      <key column="invoiceID" />
      <one-to-many class="LogisticsManagement.Core.Components.TextJob, Logistics" />
    </bag>
    <!-- chopped bits out here -->
  </class>
</hibernate-mapping>


You'd need to write the code that combined the 2 internal collections into a single coherent collection, and in addition you'd need to detect the type of object being added, but this approach would keep the mapping simple, and isolate the higher level code from the fact that the objects are coming from 2 different tables. It would only need to know that the collection can contain n types of items, not how they are stored.

e.g. (not tested or anything):
Code:
public void AddInvoiceItem(InvoiceableItem item)
{
  if (item is InvoiceVehicle)
  {
    InvoiceVehicles.Add((InvoiceVehicle)item);
  }
  else if (item is InvoiceTextJob)
  {
    InvoiceTextJobs.Add((InvoiceTextJob)item);
  }
}


I'm not going to try to include sample code for the collection, but I'd think that creating an iterator for your class would be the easiest way (at least easiest for the consuming code, and since you're only going to write the collection once and likely consume it multiple times...).

I don't think this approach should be too complicated.

Colin


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 10:38 am 
Hi Colin,

Thanks for the reply.

I did have something like this previously but my problem is how to get hibernate to look in two different tables to satisfy the one-to-many?

Even if I return a collection of Interfaces I can't see how to write the mapping file to do this.

Thanks again.

Steve


Top
  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 11:57 am 
Newbie

Joined: Wed Jun 15, 2005 11:09 am
Posts: 10
Location: Salem, MA
You use 2 different collections mapped in nHibernate to load/update the data from/to the data store and you create a 3rd collection that exposes the 2 internal collections. The third collection isn't a real collection -- it's just an implementation of the interfaces the client code will expect (IList, IEnumerable most likely). Actually, that's all a real collection is, my point is that it doesn't have its own data store.

If you look at my modificataions to the mapping example you provided, you'll notice that I renamed the one-to-many maps to give each a different name. So what you are doing is telling nHibernate to map it as if there are 2 tables (which there are) and telling the client that there is a single collection that acts as a factory to return the appropriate object type. You need to write the code in the middle that makes it appear to the client that there is a single collection.

e.g.

Code:
public class InvoiceItems : IEnumerable, IList
{
  /* in the implementation, use the 2 internal collections
     as the data source for InvoiceItems.
  */
}


I should also point out that it may be possible to do what you are trying to do in nHibernate without adopting my approach. I don't know enough about it to be able to say it isn't in there.

Colin


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.