-->
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: ClassCasteException using property-ref and composite key.
PostPosted: Mon Jul 17, 2006 4:36 pm 
Newbie

Joined: Wed Jan 11, 2006 12:59 pm
Posts: 11
I am working on mapping our java classes to legacy DB. There are two tables. Both tables use composite id's. To make matters worse, TableB's foreign key reference to table A references one column in the primary key and another column that is not part of Table A's primary key. (I know this is a bad relational model, unfortunately, changing the schema is not an option). In order to work around this problem, I decided to use the property-ref in my mapping. Unfortunately, when I excecute I get a ClassCastException. (See stack trace below) I also noticed that other people were having problem similar to this as recently as version 3.1. Is this a case of an incorrect mapping document, or is it possible this is due to the bug mentioned here: http://opensource.atlassian.com/project ... se/HB-1526

Any help would be appreciated.

Hibernate version:
3.0
Mapping documents:
<hibernate-mapping package="com.idfbins.adp">
<class name="InsuranceMaster" table="INMAST" schema="fbmtstdta" catalog="FBMAS270">
<composite-id name="inKey" class="InsuranceMasterKey">
<key-property name="company" column="INMCMPY" type="string"/>
<key-property name="policy" column="INMPRFX" type="string"/>
<key-property name="suffix" column="INMSUFX" type="string"/>
</composite-id>

<property
name="fedSuffix"
column="INMFEDSX"
type="long"
/>

<properties name="FBAltKey" insert="false" update="false">
<component name="fbKey" class="FederationMasterKey">
<property name="policy" column="INMPRFX" insert="false" update="false"></property>
</component>
<property name="fedSuffix" column="INMFEDSX" update="false" insert="false"></property>
</properties>

<set name="fedRecords"
lazy="false"

>
<key property-ref="FBAltKey">
<column name="FBPRFX"></column>
<column name="FBSUFX"></column>
</key>
<one-to-many class="FederationMaster" />
</set>

</class>
</hibernate-mapping>

<hibernate-mapping package="com.idfbins.adp">
<class name="FederationMaster" table="FBMAST" schema="fbmtstdta" catalog="FBMAS270">
<composite-id name="fbKey" class="FederationMasterKey">
<key-property name="policy" column="FBPRFX" />
<key-property name="suffix" column="FBSUFX" />
<key-property name="sequence" column="FBSEQ" />
</composite-id>

<property
name="firstName"
column="FBFNAME"
type="string"
/>

<property
name="lastName"
column="FBLNAME"
type="string"
/>



</class>
</hibernate-mapping>

Full stack trace of any exception that occurs:

14:33:54,772 DEBUG LongType:86 - returning '1' as column: INMFEDSX5_0_
14:33:54,772 DEBUG StringType:86 - returning '76829' as column: INMPRFX5_0_
14:33:54,772 DEBUG LongType:86 - returning '1' as column: INMFEDSX5_0_
14:33:54,772 DEBUG Loader:429 - done processing result set (1 rows)
14:33:54,788 DEBUG AbstractBatcher:313 - about to close ResultSet (open ResultSets: 2, globally: 2)
14:33:54,788 DEBUG AbstractBatcher:298 - about to close PreparedStatement (open PreparedStatements: 2, globally: 2)
14:33:54,788 DEBUG AbstractBatcher:416 - closing statement
14:33:54,788 DEBUG Loader:528 - total objects hydrated: 1
14:33:54,788 DEBUG TwoPhaseLoad:96 - resolving associations for [com.idfbins.adp.InsuranceMaster#component[company,policy,suffix]{policy=76829, suffix=1, company=1}]
Exception in thread "main" java.lang.ClassCastException: com.idfbins.adp.InsuranceMaster
at org.hibernate.type.CollectionType.getKeyOfOwner(CollectionType.java:313)
at org.hibernate.type.CollectionType.resolve(CollectionType.java:326)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:105)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:530)
at org.hibernate.loader.Loader.doQuery(Loader.java:436)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1345)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:116)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:101)
at org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2471)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:75)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:643)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:59)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:84)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:134)
at com.idfbins.adp.InsuranceMaster$$EnhancerByCGLIB$$1e70e55f.getFbKey(<generated>)
at com.idfbins.adp.MyTest.main(MyTest.java:26)

Name and version of the database you are using:
DB2 UDB


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 17, 2006 10:25 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That mapping can't work because FederationMasters don't know anything about the company property. In a normal one-to-many collection, the members of the collection contain a reference to the owning entity's primary key: in your case, you can't. In fact, unless there is only one value for company, nothing you can do to the mapping will make it correct (though you can make it funcitonal). And if company has only one possible value, it shouldn't be in the id (though you can leave it in the primary key, if you like).

To make your mapping functional (but not strictly correct), add in the inverse mapping (the many-to-one from the FederationMaster to the InsuranceMaster). Hibernate will use that mapping instead of the default primary key mapping to build the collection.

The reason I say that the collection will never be strictly correct, is because even if you put in that many-to-one, it's only going to map to the INMPRFX and INMSUFX columns. So if you get two InsuranceMasters with the same values in those columns, but different values in the INCMPY column, then your mapping breaks and Very Bad Things happen.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 18, 2006 11:24 am 
Newbie

Joined: Wed Jan 11, 2006 12:59 pm
Posts: 11
tenwit,

Thanks for your help. Your explanation has helped clear things up a little, but I am still having trouble. I added the many-to-one mapping to the Federation mapping document, but I am still getting a ClassCastException. Perhaps I missed something. My mapping documents with the suggested changes are found below.


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping package="com.idfbins.adp">
    <class name="InsuranceMaster" table="INMAST" schema="fbmtstdta" catalog="FBMAS270">
        <composite-id name="inKey" class="InsuranceMasterKey">
           <key-property name="company" column="INMCMPY" type="string"/>
           <key-property name="policy" column="INMPRFX" type="string"/>
           <key-property name="suffix" column="INMSUFX" type="string"/>
        </composite-id>
       
        <property
           name="fedSuffix"
           column="INMFEDSX"
           type="long"
        />
       

   <properties name="FBAltKey" insert="false" update="false">
      <component name="fbKey" class="FederationMasterKey">
         <property name="policy" column="INMPRFX" insert="false" update="false"></property>
      </component>
      <property name="fedSuffix" column="INMFEDSX" update="false" insert="false"></property>
   </properties>
   
   <set name="fedRecords" lazy="true" inverse="true">
      <key property-ref="FBAltKey">
         <column name="FBPRFX"></column>
         <column name="FBSUFX"></column>
      </key>
      <one-to-many class="FederationMaster" />
   </set>
      

   </class>   
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping package="com.idfbins.adp">
    <class name="FederationMaster" table="FBMAST" schema="fbmtstdta" catalog="FBMAS270">
        <composite-id name="fbKey" class="FederationMasterKey">
           <key-property name="policy" column="FBPRFX" />
           <key-property name="suffix" column="FBSUFX" />
           <key-property name="sequence" column="FBSEQ" />
        </composite-id>
       
        <property
           name="firstName"
           column="FBFNAME"
           type="string"
        />
       
        <property
           name="lastName"
           column="FBLNAME"
           type="string"
        />
       
        <many-to-one  name="insMaster" property-ref="FBAltKey"  class="InsuranceMaster" insert="false" update="false">
         <column name="FBPRFX"></column>
         <column name="FBSUFX"></column>
      </many-to-one>         
       
   </class>   
</hibernate-mapping>


Here is the stack trace:

09:23:31,005 DEBUG LongType:86 - returning '1' as column: INMFEDSX5_0_
09:23:31,005 DEBUG StringType:86 - returning '76829' as column: INMPRFX5_0_
09:23:31,005 DEBUG LongType:86 - returning '1' as column: INMFEDSX5_0_
09:23:31,005 DEBUG Loader:429 - done processing result set (1 rows)
09:23:31,005 DEBUG AbstractBatcher:313 - about to close ResultSet (open ResultSets: 2, globally: 2)
09:23:31,005 DEBUG AbstractBatcher:298 - about to close PreparedStatement (open PreparedStatements: 2, globally: 2)
09:23:31,005 DEBUG AbstractBatcher:416 - closing statement
09:23:31,020 DEBUG Loader:528 - total objects hydrated: 1
09:23:31,020 DEBUG TwoPhaseLoad:96 - resolving associations for [com.idfbins.adp.InsuranceMaster#component[company,policy,suffix]{policy=76829, suffix=1, company=1}]
Exception in thread "main" java.lang.ClassCastException: com.idfbins.adp.InsuranceMaster
at org.hibernate.type.CollectionType.getKeyOfOwner(CollectionType.java:313)
at org.hibernate.type.CollectionType.resolve(CollectionType.java:326)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:105)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:530)
at org.hibernate.loader.Loader.doQuery(Loader.java:436)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1345)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:116)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:101)
at org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2471)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:75)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:643)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:59)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:84)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:134)
at com.idfbins.adp.InsuranceMaster$$EnhancerByCGLIB$$1e74b8dd.toString(<generated>)
at java.lang.String.valueOf(String.java:2577)
at java.io.PrintStream.print(PrintStream.java:616)
at java.io.PrintStream.println(PrintStream.java:753)
at com.idfbins.adp.MyTest.main(MyTest.java:38)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 18, 2006 5:45 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
The class cast is probably because of the component. You're trying to get hibernate to match a {String, String} object (the key in the set and many-to-one) to a { FederationMasterKey, String } object (the FBAltKey properties). It might work if you remove the component, or if you put both columns into the component, instead of just one.

I have to ask though: if you believe that policy+suffix is "unique enough" to be at the one end of a many-to-one, then why is company part of the ID? Just because it's in the primary key of the table doesn't mean that it has to be in the ID of the mapping, and if removing the company column from the ID makes the rest of your mapping simpler and more understandable, I think that you should do that. And if policy+suffix isn't "unique enough", then you should be using a many-to-many relationship, not a many-to-one.

_________________
Code tags are your friend. Know them and use them.


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.