-->
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: Mismatch CGLIB classes with table per hierarchy inheritance
PostPosted: Fri Jul 15, 2005 1:02 am 
Newbie

Joined: Wed Jun 15, 2005 1:55 am
Posts: 4
Location: Sydney,Australia
When I fetch a "Form" object which includes a list of "Field" objects, due to lazy fetching (?), proxy objects (is this the right term) are created using CGLIB for the contained "Field" objects.

The proxy object class generated is a subclass of the top class of the table per class hierarchy "Field" and cannot be cast into subclasses of the top class eg "BigField". (ClassCastException)

Bizarrely, if I call via the proxy object a method in Field that is overriden in a subclass eg toString(), the correct method is called and properties of the correct subclass are viewable (and have been correctly fetched from the database).

This means that I cannot have additional attributes in the subclasses of "Field" unless there are corresponding assessors defined in the top level class "Field" which have to be broken in some subclasses - yuk.

Note that if a proxy object does not need to be created an object of the
correct subclass is created.

Any one got any idea on how to get CGLIB to create the correct
proxy object class?

Alternatively any idea how to get to the "real" object via the proxy object?
(Probably insane as the property change listeners would be bypassed)



[b]Hibernate version: 3.02[/b]

[b]Mapping documents:

[code]
class Field {
Integer normal;
public String toString() {
return "Normal value " + normal;
}

}
class BigField extends Field{
Long big;
public String toString() {
return "Bigvalue " + big;
}
class Form {
List fields;
}
-- appropriate getters and setters configured --

<class name="org.x.Field" table="field">
<discriminator column="field_type" type="string"/>
<id name="id"....
<property name="normal" type="java.lang.Integer" ..../>

<subclass name="org.x.BigField" discriminator-value="Big">
<property name="big" type="java.lang.Long" ..../>

</subclass>
</class>

<class name="org.x.Form" table="form">
<id ...../>
<list name="fields" table="field" lazy="false"
cascade="save-update">
<cache
usage="read-write" />
<key column="form_id"> </key>
<index column="field_number"/>
<one-to-many
class="org.x.Field" />
</list>
</class>


[/code]
[/b]

[b]Code between sessionFactory.openSession() and session.close():[/b]

Save a Form with a BigField value 100
After the fetch of the form....

Field field= (Field) form.getFields().get(0);

log.debug(" field " + field);
>>>>> field Bigvalue 100

log.debug(" field class" + field.getClass().getName());
>>>>> field class org.x.Field$$EnhancerByCGLIB$$f9fce7de

BigField big = (BigField)form.getFields().get(0);

...... Throws a ClassCastException

[b]Name and version of the database you are using: [/b]
Postgresql 7.4.8
[b]The generated SQL (show_sql=true):[/b]

[b]Debug level Hibernate log excerpt:[/b]


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 1:30 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
"Any one got any idea on how to get CGLIB to create the correct
proxy object class?"
Real object type is not known before loading it from database and it can not be changed after loading.

"Any one got any idea on how to get CGLIB to create the correct
proxy object class?
"

Cast it to HibernateProxy, it has a getter.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:14 am 
Newbie

Joined: Wed Jun 15, 2005 1:55 am
Posts: 4
Location: Sydney,Australia
Thanks Baliukas,

I think the stuff in http://www.hibernate.org/hib_docs/v3/re ... ng-proxies
make it clearer what the problem is.

The suggestion is to use interfaces for each class in the hierarchy.
Will the proxy class automatically "implement" all the subclass interfaces?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:42 am 
Newbie

Joined: Wed Jun 15, 2005 1:55 am
Posts: 4
Location: Sydney,Australia
My work around is a casting accessor which is used where the type is known.

public BigField getBigField() {
if ( field instanceof BigField)
return field;
else
return (BigField)(((HibernateProxy)field).getHibernateLazyInitializer().getImplementation());
}

This will work regardless of persistance state of object.


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.