-->
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.  [ 6 posts ] 
Author Message
 Post subject: Unmapped class in inheritance hierarchy
PostPosted: Thu Jun 30, 2005 7:13 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
I have the following class structure:
    A is abstract and mapped.
    B inherits from A and is abstract, but has no map.
    C inherits from A and is concrete and mapped as joined-sublass.
    D inherits from B and is concrete and mapped as joined-sublass.
    E inherits from B and is concrete and mapped as joined-sublass.
    F inherits from E and is concrete and mapped as joined-sublass. It has a property that is a collection of A's, and another that is a collection of B's.
    G is concrete class that has a property of type B, and is mapped. It does not inherit from anything other than Object.
Note that the B class is NOT mapped. This is at the root of my problem. It is not mapped to a database table because it doesn't add data to A, just behaviour.

I have the following (somewhat obvious) table structure:
    TA is a table that has 1 row for each A object.
    TC is a table that has 1 row for each C object and is matched to a row in TA.
    TD is a table that has 1 row for each D object and is matched to a row in TA.
    TE is a table that has 1 row for each E object and is matched to a row in TA.
    TF is a table that has 1 row for each F object and is matched to a row in both TA and TE.
    TFA is a linking table that has a row for each object in the A property of F.
    TFB is a linking table that has a row for each object in the B property of F.
    TG is a table that has a row for each G object. It has a column for the ID of the B object it refers to, which will have a match in TA as well as one of TC, TD, or TE (and possibly TF).
Ok so far? My problem is this. When I try to map the B property of G, it fails. It throws a CGLIB exception:

> org.hibernate.PropertyAccessException: exception setting property value with CGLIB

I can't map the B property of G as a B because B is not mapped, so I map it as an A. Since A and B are abstract, I know that I am really getting back a C, D, E, or F. These all extend B, so you may think I'd be good to go, right? Wrong. For some reason I don't understand, hibernate is creating a proxy object that is only a proxy for A.

Funnily enough, I don't seem to get a problem mapping the collections on class F. I map the collection of As as set of As and collection of Bs as set of As, and everything seems to work fine. I cast the elements of the set to a B and the cast succeeds.

Here are just some of the things that have been considered and/or tried to fix this:
    Relax the interface on G to accept an A, and then cast it to B. Fails on a casting exception, since this is actually a proxy object.
    As above, but also force A not to be lazy loaded. Works, but loads virtually the entire database thanks to the collections in F. Not a practical solution.
    Introduce a UserType that returns a B, but is actually a C, D, E, or F. But creating those other objects is complicated. Could we use hibernate to create the object? Do we still need a UserType then?
    Forget about Hibernate when creating a G and use raw JDBC. Once you get back the ID of the B, feed it to hibernate and use the concrete class returned.
    Create a table for B that holds only IDs. Our DBA rightly balks at a hack like this, since the only purpose of the table would be to satisfy the demands of our tool.
    Store the B in G as a set. This would require another bogus table, though, as well as altering the behaviour of G in an odd way.
    Change all the joined-subclasses to subclasses that use joins. As I understand it, this wouldn't support the collections on F, though.


So am I understanding the problem correctly? If not, what am I missing? If I do understand the problem, what do people recommend as the solution? Is this actually a hibernate bug? Is there a workaround? Any help would be appreciated.


Top
 Profile  
 
 Post subject: A hibernate3 bug?
PostPosted: Tue Jul 05, 2005 11:57 am 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
The more I think about this, the more I am becoming convinced that this is a Hibernate bug.

When I get an object of type A in other contexts, it supports the full set of functions of the underlying object. It is smart enough to know that I really have a C, D, E, or F. When I try to use the methods of a D on an object that should be a D, it works even though the HQL is requesting an A.

In this one context, however, Hibernate is not creating a proxy object with the abilities of a D or E or F. The proxy object only gives me the functions of A.

I'm thinking that is a bug. Hibernate knows this is a joined subclass, so it should give back a proxy object that has all the methods of the subclass. The fact that due to the limitations of mapping I can't map the exact level of inheritance that I want shouldn't enter into it, should it?

What do others think? I'll file it as a bug unless someone has another opinion.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 05, 2005 12:01 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This is all explained in the documentation and if you ever again ignore the forum rules use the word "bug" to describe well-understood, intended, well-documented functionality, you will be banned quick fast!


Top
 Profile  
 
 Post subject: Well-understood, intended, well-documented functionality
PostPosted: Tue Jul 05, 2005 3:11 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
I realize that you are a volunteer kindly devoting your time to us, the hibernate users. For that, I offer profuse thanks. I certainly appreciate the work you are doing.

I also understand that it can be quite frustrating having person after person claiming "it is a hibernate bug" when in fact they just haven't paid attention to the documentation. As the forum rules state, mapping is a complex issue and chances are, it is the user who has made a mistake, not the program.

Not only that, but I understood that there was a better than even chance that I was misunderstanding the situation and that there is no hibernate bug here. That is why I asked for someone to point out my error in thinking before I filed a bug report. Filing a bug report for a genuine bug is the responsibility of every good netizen, but wasting developers' time tossing out bogus bug reports helps nobody. Better that other users point out what I was missing.

In short, I was trying to do the right thing. While I appreciate your frustration, it would be a good thing if people could feel a bit more comfortable asking questions here. Aggressive responses is one of the things that give open source a bad name. You must act as you see fit, ban me if you feel you must, but I for one would appreciate a more moderate tone, even if it turns out I have been a dufus.

Now, as to the specifics of your reply. Perhaps you are right that it is well documented, but my inability to see it is not for lack of trying. I've read the reference manual and "Hibernate in Action" cover to cover. I've googled and searched the forums. I probably just didn't get the right combination of words, but I never saw the answer to my problem. Nor did another developer who worked the problem with me.

Maybe it is so obvious we are just missing it. If you want to call me a moron for not seeing the answer, I can plead guilty to that. I listed some of the things that have been tried to resolve the problem. Since then we have come up with a workaround, but I'm still not sure what was wrong with my analysis about how the proxy object is acting versus how it should act. Time to dive into the code, I guess, so I can understand things better.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 05, 2005 3:35 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
http://www.hibernate.org/hib_docs/v3/re ... ng-proxies



Think about the problem. It is impossible to tell what concrete class sits at the other end of the association at the time the proxy is instantiated, since you would have to hit the associated database table to do that, and the whole point of the proxy is to *avoid* hitting the associated table.

You can easily typecast by calling session.get() or session.load().


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 05, 2005 5:05 pm 
Newbie

Joined: Fri Feb 25, 2005 3:40 pm
Posts: 8
Location: Victoria, BC Canada
Ahh, the light is finally beginning to dawn.

When I was thinking about proxies, I was mixing my thinking between proxies on the owning objects (ie. call database if property is null) versus owned objects. Your message clarified my thinking here. Yes, I get what you are saying.

Let me make sure I also understand what you are saying about using get() or load():

I load a G g which has a proxy object for A. I get the Id of A by calling g.getA().getId(). I get a new proxy reference to A (but that has the full concrete class API) by calling session.get("A", aId). Now, G will still have the old proxy object, so I have to call g.setA(newA).

Will that work? What causes me to ask is this quote from the javadoc of session.get():

Quote:
If the instance, or a proxy for the instance, is already associated with the session, return that instance or proxy.


So do I have to get out of the existing session to make this work? And is changing the property on G a safe operation that won't cause unexpected side effects?

Thanks for your help, I really do appreciate it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.