-->
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.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Mapping two classes to same table?
PostPosted: Sun Mar 02, 2008 6:54 am 
Regular
Regular

Joined: Tue Apr 10, 2007 10:02 am
Posts: 56
Is there anything wrong about having two Java classes mapped to the same table?

I have an entity (e.g. course) that has a number of related sub entities (e.g. attendees, class times etc) but I don't want to include these sub entities as properties in the main entity class structure.

To get around this I'm using the following class hierarchy...

Code:
AbstractCourse
    |---- Course
    |---- CoursePlusBookings

public abstract class AbstractCourse {
   private int CourseID;
   private String Title;
   private String Teacher
}

public class Course extends AbstractCourse {
}

public class Attendee {
   private int AttendeeID;
   private int CourseID;
   private String StudentName;
}

public CoursePlusBookings extends AbstractCourse {
   private set Attendees;
}



The class 'AbstractCourse' contains all the properties associated with a school class.

The class 'Course' is a sub class of 'AbstractCourse'. I have a normal set of create, read and update operations active against this class.

The class 'CoursePlusBookings' is a class that includes collections of related entities like 'Attendees'. I use the 'delete' method on this class
as the Hibernate mapping includes a'cascade delete' element. That way when I delete a 'CoursePlusBookings'instance the related 'Attendee' instances are deleted as well.

Is this a sound way to manage persistence using Hibernate?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 1:42 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
The name CoursePlusBooking seems to hint to a design flaw. But that is unrelated to Hibernate.

Hibernate wise such an approach is fine. Just make sure to make the proper inheritance mapping.

Jens

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 5:09 am 
Regular
Regular

Joined: Tue Apr 10, 2007 10:02 am
Posts: 56
What do you mean by inheritance mapping?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 7:39 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
davout_uk wrote:
What do you mean by inheritance mapping?


http://www.hibernate.org/hib_docs/refer ... tance.html

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 8:20 am 
Regular
Regular

Joined: Tue Apr 10, 2007 10:02 am
Posts: 56
... I don't see how mapping inheritance relates to this problem.

The core question is about having a main entity that maps to a table that has subordinate sub entities but for normal usage I don't want the sub entities included in the main class.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:05 pm 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
davout_uk wrote:
... I don't see how mapping inheritance relates to this problem.

The core question is about having a main entity that maps to a table that has subordinate sub entities but for normal usage I don't want the sub entities included in the main class.


What do you mean by "sub entities included in the main class"?

From the previous posts you have 3 classes that build a inheritance tree. As far as I understand it, you want at least two of them mapped to a single table. The way to do this is called inheritance mapping in the hibernate universum.

Jens

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 13, 2008 10:33 pm 
Newbie

Joined: Mon Nov 19, 2007 9:01 am
Posts: 8
OK, so this looks kind of like "table per class hierarchy" (http://www.hibernate.org/hib_docs/refer ... leperclass).

But what should the discriminator value be? In this scenario, every record could be mapped by either class (that sounds a bit odd, but see the scenario at the end). And will it cause problems if you have two objects , one from each class, that map to the same row?

Another way to look at this is:

Course
|---- CoursePlusOptionalAssociations

CoursePlusOptionalAssociations only exists to add associations to Course. And then the question becomes:

How do I map a subclass which has no properties (and therefore needs no table) but does need to represent one end of an association?

Why would we want to do this? Let's imagine that Course is part of a framework or subdomain that sits underneath other parts of our domain model. We might have dozens of higher level modules that might want to associate with Course - billing, enrolments, timetabling etc. We might even want to access that same Course domain model from an entirely different application.

In this scenario, it's clearly inappropriate for the Course module to include association mappings to all the higher level modules. It's much better for the higher level modules to extend or decorate Course to include their own specific properties and associations, so you'd have BillingCourse, EnrolmentsCourse etc.

So what should the mapping for BillingCourse look like? It's equally inappropriate for the BillingCourse mapping to repeat all the mapping details that we already have in the Course mapping file - not DRY and a breach of encapsulation. If BillingCourse has persistable properties, we create a BillingCourse table and use "table per concrete class" using the nice <subclass extends=""...> mapping.

But what if BillingCourse has no persistable properties and extends Course only to provide an endpoint for associations to other billing objects? AFAIK, our options are:

1. Create a BillingCourse table anyway, purely to hang a subclass mapping on.
2. Have BillingCourse map back to the Course table. Just a very simple mapping with just the PK would do for this purpose.
3. Define BillingCourse as a <subclass> of Course with a discriminator that will include every row. Probably means that we have to use a different session factory for each high-level module.


If we choose the second option, this scenario starts to look very like the OP's "two classes mapping to one table" scenario.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 16, 2008 5:40 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
Ok, I think I now get where you are heading.

1. What you are looking for is not only to map two classes to the same table, but two classes two one row. I don't think this is (or should be) possible. Hibernate wouldn't be able to tell which class to create from the table.

2. Try what I personally refer to as Role-pattern. I don't know if it has some official name. The purpose of that pattern is to seperate different usages of a class from the class itself.

It would look something like this:

interface Course{
public CourseRole getRole(Class<?>)
};

abstract class CourseRole extends Course{
Course course // use delegation to this in order to implement the course Interface
}


class CourseImpl implements Course{
private Map<Class<?>,CourseRole> courseRole
}

class BookableCourse extends CourseRole;

class BillableCourse extends CourseRole;

Go ahead and map this to Hibernate in Order to keep the Course Interface and it's implementation independent of all the references to the Course.

HTH
Jens

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 16, 2008 7:48 pm 
Newbie

Joined: Mon Nov 19, 2007 9:01 am
Posts: 8
Jens,

So what would the mapping look like?

Jaime


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 17, 2008 1:10 am 
Pro
Pro

Joined: Tue Aug 26, 2003 8:07 pm
Posts: 229
Location: Brisbane, Australia
schauder wrote:
1. What you are looking for is not only to map two classes to the same table, but two classes two one row. I don't think this is (or should be) possible. Hibernate wouldn't be able to tell which class to create from the table.


I think this will work - the only issue will be if your try to load a single row as both classes at the same time in the same session, in which case you'll need to evict the old one from the session before you can load the new one.

The idea was that one version represented a kind of "light" version of the object. I seem to remember this approach being recommended as a workaround for Hibernate not supporting "lazy properties". I don't remember if there were any issues with this approach though (other than the already mentioned one about not being able to load instances of both classes for the same row at the same time).

Doesn't Hibernate now support lazy properties though? Maybe that approach might work better for you?

_________________
Cheers,
Shorn.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 18, 2008 12:28 pm 
Newbie

Joined: Fri May 19, 2006 9:07 am
Posts: 3
In the example of davout_uk AbstractCourse should be annotated with @MappedSuperclass and it should work fine without any additional inheritance annotations.

What didn't work for me is to eliminate the AbstractCourse class, just use Course and extend from it. In that case Hibernate complains that there is a missing discriminator type column. IMO it should work as with the abstract class.

Cheers,
Yuri


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 20, 2008 9:22 am 
Newbie

Joined: Fri Jun 20, 2008 8:44 am
Posts: 2
Location: Montreal, CA
I was looking for something similar and found another solution. I have a class with a limited number of attributes for listing entries on a web page. I have another class that extends the first one to provide full detail when the user clicks on one of the entries.

To make this work I had to specify the "entity-name" attribute on the "class" tag. Otherwise Hibernate would load each row twice, once for each mapped class. I used the the same value as the "name" attribute for the "entity-name" attribute.

Something similar is mentionned in the manual at http://www.hibernate.org/hib_docs/refer ... entityname,
but in the manual it is the same class that is mapped twice using 2 distinct entity names.

Nick


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 20, 2008 9:24 am 
Newbie

Joined: Fri Jun 20, 2008 8:44 am
Posts: 2
Location: Montreal, CA
Deleted accidental double post.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 23, 2008 10:08 am 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
Well, this definitely looks like a compound set of classes going to one table, as opposed to inheritance. Mapping such a relationship is quite easy with Hibernate, especially if you're using JPA. I map a relationship like this one in a free Hibernate3 tutorial on my website:

Image

It's rather simple, Just make one class the primary entity, and the second, an embeddable entity. Here's the code for the embedded entity:

http://jpa.ezhibernate.com/Javacode/learn.jsp?tutorial=14mappingtwoclassestoonedatabasetablejpahibernate

Code:
package com.examscam.mappings;
import javax.persistence.Embeddable;

@Embeddable
public class ThingDetail {

   private String alias;
   private int count;

   public String getAlias() {return alias;}
   public void setAlias(String alias) {
      this.alias = alias;
   }

   public int getCount() {return count;}
   public void setCount(int count) {
      this.count = count;
   }
}



And here's the core entity using the embedded class:

Code:
package com.examscam.mappings;
import javax.persistence.*;
import org.hibernate.Session;
import com.examscam.HibernateUtil;

@Entity
public class Thing {
  private long id; 
  private String name;

  private ThingDetail thingDetail;

@Embedded
  public ThingDetail getThingDetail(){
    return thingDetail;
  }
  public void setThingDetail(ThingDetail detail) {
    this.thingDetail = detail;
  }

  @Id
  @GeneratedValue
  public long getId() {return id;}
  public void setId(long id) {this.id = id;}

  public String getName() {return name;}
  public void setName(String name) {this.name = name;}
}


I'ts just that easy!

http://jpa.ezhibernate.com/Javacode/learn.jsp?tutorial=14mappingtwoclassestoonedatabasetablejpahibernate

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 18, 2008 4:07 am 
Newbie

Joined: Mon Nov 19, 2007 9:01 am
Posts: 8
Cameron,

This is a nice explanation of embedded components, but differs from the OP's and my scenarios in two important ways:

1. You split the fields of table thing across classes Thing and ThingDetail. In our scenarios, all the fields of the table would be on class Thing. ThingDetail would have no scalar properties.

2. Your ThingDetail has no associations with other entities. Table thing has no foreign keys. In our scenarios, ThingDetail would have collection-valued properties implementing associations to other entities.

I'd love to know if embedded components can support this scenario.

Jaime Metcher


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 19 posts ]  Go to page 1, 2  Next

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.