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.  [ 5 posts ] 
Author Message
 Post subject: Inheritance Problem with the "table per subclass"
PostPosted: Fri Oct 07, 2005 9:59 am 
Newbie

Joined: Thu Oct 06, 2005 8:08 pm
Posts: 19
Inheritance Problem with the "table per subclass" aka "joined-subclass" model

My HQL query is returning instances of the base class rather than the correct derived class. I was wondering if this is normal or if I am doing something wrong. Please help!

Simplified class structure:

Code:
class A
{
   private int id;
   private B b;   // Reference to class b

   // trivial getters/settters
};

class B
{
   private int id;
   private String someData;

   // trivial getters/settters
};

class C extends B
{
   private String derivedClassData;

   // trivial getters/settters
};


C.hbm.xml:

Code:
<joined-subclass
      name="package.C"
      table="C"
      extends="package.B">
   <key column="ID"/>

   <property name="derivedClassData" column="DerivedClassData" type="string" not-null="true"/>
</joined-subclass>


My simplified code:

Code:
   Session session = HibernateUtil.getCurrentThreadSession();   
   try {   
      Query query = session.createQuery("from A as a");
      searchResults = query.list();

      for (Object o : searchResults) {
         A a = (A) a;
         B b = a.getB();

         // This will throw ClassCastException. Hibernate always returns direct instances of B
         // and never detects and creates the derived instances of C. Is there any way to get it
         // to do that? For this problem, trust me that every B instance will be a direct instance of C.
         C c = (C) b;
      }
   } finally {
      HibernateUtil.closeSession();
   }


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 07, 2005 11:27 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Interesting.

Did you try

Code:
Query query = session.createQuery("from B as b");

or
Code:
Query query = session.createQuery("from C as c");


?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 07, 2005 11:45 am 
Beginner
Beginner

Joined: Mon Sep 27, 2004 4:28 pm
Posts: 44
Hibernate is really good about keeping us honest with Polymorphism. If you have a relationship with the base class, it assumes that's what you want. If you know it's an instance of C, then you can certainly do the following:

C c = (C) session.get(C.class, b.getId());

Hibernate is building you a collection of B objects, but avoiding the potentially numerous queries it would take to gather all of the subclass data. Whenever I run into this problem with Hibernate, it occurs to me that I'm probably using polymorphism poorly... For instance, if your class will always be a 'C'.. then maybe you should give A a relationship to C instead?

I believe you can also make this behavior go away by disabling the proxying of your inherited classes... This way hibernate can't create a base-class proxy, and will instead need to construct real instances of your classes.

Hope this is helpful, it's been a while since I've run into this so there's a chance I'm misspeaking :)

Phill


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 07, 2005 12:30 pm 
Newbie

Joined: Thu Oct 06, 2005 8:08 pm
Posts: 19
famousactress wrote:
For instance, if your class will always be a 'C'.. then maybe you should give A a relationship to C instead?


With the simplified scenario I presented that would be a good idea. In fact, I really don't need inheritance at all if this was my end goal; however, in the near future I will need inheritance and A will need to refer to derived classes of B other than C, so I would like to get this class model working.

Thanks guys. You've both given me two ideas to try:

- "from B as b". I know "from C as c" works but this will test that inheritance is setup correctly.
- Setting class B to abstract. It doesn't have any abstract members but conceptually it should be abstract since there should never be a direct instance of B. This might help Hibernate load the proper instances.

I will try these tonight and post the results. Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 07, 2005 12:37 pm 
Beginner
Beginner

Joined: Mon Sep 27, 2004 4:28 pm
Posts: 44
Beware that setting B to abstract might not solve your problem. Hibernate via CGLib will still be able to create proxy classes of B and return them to you. I believe the real way to stop this from happening is by setting lazy="false" at the class level of your hbm.xml mapping.

Oh, and you're welcome.. feel free to press the "Yes, this helped me button on our posts to give us credits :) "

Good luck,
Phill


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.