-->
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.  [ 11 posts ] 
Author Message
 Post subject: Lightweight Class and eager fetching
PostPosted: Mon Jul 26, 2004 11:15 am 
Newbie

Joined: Mon Jul 26, 2004 11:07 am
Posts: 6
I have a class, let's say it's Cat, and this class has a many-to-one mapping to a class Owner. The Owner class is complex, so I created an OwnerSummary class, which Owner extends, such that I have lightweight and heavyweight versions. Cat has an OwnerSummary as an attribute. (Standard Lightweight Class implementation)

The catch is this - I'd like to be able to specify, in HQL, which version of Owner should be loaded. The standard approach:

select cat from Cat cat
inner join fetch cat.owner

would load the OwnerSummary. Is there a way to express in HQL that the complex Owner object will be loaded instead?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 26, 2004 11:33 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Map two associations, both lazy.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 26, 2004 12:31 pm 
Newbie

Joined: Mon Jul 26, 2004 11:07 am
Posts: 6
So as I understand it, you're suggesting that Cat have both an Owner and an OwnerSummary mapped, many-to-one, both proxied so as to lazy load them. Further, at most one of these attributes can be populated at any given time.

I will give this a try.


Top
 Profile  
 
 Post subject: Problem with this
PostPosted: Mon Aug 16, 2004 3:38 pm 
Newbie

Joined: Mon Jul 26, 2004 11:07 am
Posts: 6
I've tried what I said I was going to - I have the owner class mapped:

<hibernate-mapping>
<class
name="eg.Owner"
table="owner"
dynamic-update="false"
dynamic-insert="false">

<id
name="id"
column="idma_cllctn_rqst_id"
type="java.lang.Integer">
<generator class="identity"/>
</id>

<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="name"
/>

<many-to-one name="catSummary" class="eg.CatSummary"
outer-join="false" insert="false" update="false">
<column name="cat_id"/>
<column name="id2"/>
</many-to-one>

<many-to-one name="cat" class="eg.CatDetail" outer-join="false"
insert="false" update="false">
<column name="cat_id"/>
<column name="id2"/>
</many-to-one>
</class>
</hibernate-mapping>

And the cat classes:

<hibernate-mapping>
<class
name="eg.CatSummary"
table="cat"
proxy="eg.CatSummary"
dynamic-update="false"
dynamic-insert="false">

<composite-id name="catId" class="com.sprichards.data.CatId">
<key-property name="catId" column="cat_id"
type="java.lang.Long"/>
<key-property name="id2" column="id2"
type="java.lang.String"/>
</composite-id>

<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="name"
/>
</class>
</hibernate-mapping>

and

<hibernate-mapping>
<class
name="eg.CatDetail"
table="cat"
proxy="eg.CatDetail"
polymorphism="explicit"
dynamic-update="false"
dynamic-insert="false"
>

<composite-id name="catId" class="com.sprichards.data.CatId">
<key-property name="catId" column="cat_id"
type="java.lang.Long"/>
<key-property name="id2" column="id2"
type="java.lang.String"/>
</composite-id>

<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="name"/>
<property
name="color"
type="java.lang.String"
update="true"
insert="true"
column="name"/>
<property
name="color"
type="java.lang.String"
update="true"
insert="true"
column="breed"
/>
</hibernate-mapping>

CatDetail extends CatSummary.

I have the HQL query:

from Owner as ow
inner join fetch ow.catSummary
where ow.name = :name

When executed under Hibernate 2.1.6 (and 2.1.3) I get:

15:20:53,633 DEBUG [SessionImpl] attempting to resolve [eg.CatDetail#CatId: 473 and Id2: A47324 ]
15:20:53,633 DEBUG [SessionImpl] resolved object in session cache [eg.CatDetail#CatId: 473 and Id2: A47324
]
15:20:53,643 ERROR [BasicPropertyAccessor] IllegalArgumentException in class: eg.Owner, setter method of property: cat
15:20:54,594 ERROR [BasicPropertyAccessor] expected type: eg.CatDetail, actual value: CatSummary

What should I be doing differently to get this to work?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 4:49 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
[/quote]15:20:53,643 ERROR [BasicPropertyAccessor] IllegalArgumentException in class: eg.Owner, setter method of property: cat
15:20:54,594 ERROR [BasicPropertyAccessor] expected type: eg.CatDetail, actual value: CatSummary
Quote:

what about this? are you sure of your pojos and mapping files?

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 5:23 pm 
Newbie

Joined: Mon Jul 26, 2004 11:07 am
Posts: 6
I've combed over the mappings a few times. The attribute typers match the types in the mappings. It seems to me that the problem may lie in Hibernate trying to resolve CatSummary.

It seems that in an optimization attempt, Hibernate checks its session cache to see if the related CatDetail exists (if not, it will use the proxy). Because it finds a matching ID, I think it's trying to jam that located CatSummary into the CatDetail field, in spite of the fact that it doesn't actually match.

I've specified a proxy for both objects, and outer-join="false" for both objects, yet it still tries to resolve it. I'm thinking that this may cause problems as long as it tries to resolve CatDetail. Thoughts on how to work around this?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 5:33 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Ick, didn't think of that.

A crappy workaround might be to just map CatSummary to table="CAT", and CatDetails to table="cat" (uppercase vs. lowercase).

I've often wondered whether we should use the entity name, rather than the table for doing unique-ing. I might even decide to change it, in light of this discussion.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 6:00 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Yeah, decided to change it (wow, that was an ancient decision!)

For a workaround in 2.1.6, simply extend EntityPersister and override getIdentifierSpace(). Specify <class persister="MyPersister"/>.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 6:02 pm 
Newbie

Joined: Mon Jul 26, 2004 11:07 am
Posts: 6
The hack/workaround works nicely, so that's good enough for me. I understand it's a bit tough to guess what strange ways people are going to use Hibernate.

Switching uniqueness to the entity instead of the table obviously takes some potential optimizations out of the picture (such as being able to resolve a known CatDetail in cache and place it in a CatSummary field, though that might have behavioral implications as well), but would be nice in that it removes some of the restrictions on the lightweight object pattern (that whole session.evict() thing), and would make this a non-issue.

Whether or not you make the change, this workaround is good enough for now. I've added a blurb on it at http://www.hibernate.org/41.html


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 6:13 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Switching uniqueness to the entity instead of the table obviously takes some potential optimizations out of the picture (such as being able to resolve a known CatDetail in cache and place it in a CatSummary field.


Yeah, I think thats why I originally made that decision (back in the dim, dark days of Hibernate 0.9.x), but now I don't think its a very safe optimization, and I'm struggling to think of real usecases.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 08, 2004 12:27 pm 
Newbie

Joined: Tue Oct 07, 2003 3:58 pm
Posts: 16
Location: Netherlands
I just stumbled upon very similar problem

here's my mapping

<?xml version="1.0"?>

<hibernate-mapping>
<class
name="OperatorSession"
table="OPERATOR_SESSION"
dynamic-update="false"
dynamic-insert="false"
>

<id
name="id"
column="id"
type="java.lang.String"
length="20"
>
<generator class="foreign">
<param name="property">lock</param>
</generator>
</id>

<property
name="assignment"
type="serializable"
update="true"
insert="true"
>
</property>

<property
name="registeredMessages"
type="serializable"
update="true"
insert="true"
>
...

after running rather long (~20 minutes) stress load test with presumably thousands reads/writes, the following occures

2004-09-08 14:48:18,349 ERROR [VTA12 :1094663222276:1612971 ] - BasicPropertyAccessor - IllegalArgumentException in class: OperatorSession, setter method of property: assignment
2004-09-08 14:48:18,349 ERROR [VTA12 :1094663222276:1612971 ] - BasicPropertyAccessor - expected type: SelfDirtyChecking, actual value: java.util.HashSet

when I look into the database, I see that two BLOB values are actually swapped: value of type SelfDirtyChecking sits in 'registeredMessages' field, whereas HashSet sits there in 'assignment' field

when I look back to logs, this OperatorSession was ALWAYS hit in the very same time with another OperatorSession

should I try the abovementioned workaround with custom EntityPersister?


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