I'm attempting to define an association between tables with composite primary keys using a join table. In the example below I have a client with zero or more intermediaries (which are themselves records in the client table). The problem I have is that only one of the key columns (clientRef) can be used to perform the join as sequenceNo and effectiveDate are unique to each record and are not held on the join table. To get around this I defined a duplicate property (clientReference) to be used as the property-ref in the association.
The generated SQL seems OK, however when loading the list of intermediaries I get an IllegalArgumentException because Hibernate is attempting to call getClientRef() on the property , which it expects it to be of type ClientPK.
Am I going about this the right way or is there a better way of defining the association?
Thanks in advance.
Hibernate version:
3.1
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.purpleknot.ifb.core.client.bean">
<class name="PKClientDetailBean" table="CLTCEN">
<composite-id name="clientKey" class="PKClientBean$PKClientPK">
<key-property name="clientRef" column="CLRFDG"/>
<key-property name="effectiveDate" column="CLEFDG"/>
<key-property name="sequenceNo" column="CLSQDG"/>
</composite-id>
<!-- duplicate ref to support foreign keys -->
<property name="clientReference" column="CLRFDG" insert="false" update="false"/>
<property name="role" column="INRODG"/>
<property name="forename" column="CLFNDG"/>
<property name="surname" column="CLSNDG"/>
<property name="companyName" column="CLCNDG"/>
<!-- client may have multiple intermediaries - associated through join table -->
<set name="intermediaries"
table="CLTINT"
inverse="true"
cascade="none"
lazy="false">
<key column="CLRFIK" property-ref="clientReference"/>
<many-to-many column="INRFIK"
unique="false"
class="PKClientDetailBean"
property-ref="clientReference" >
</many-to-many>
</set>
<!-- intermediary may have multiple clients -->
<!--set name="clients"
inverse="true"
table="CLTINT">
<key column="INRFIK" property-ref="clientReference"/>
<many-to-many column="CLRFIK"
class="PKClientDetailBean"
property-ref="clientReference"/>
</set-->
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
Criteria criteria = s.createCriteria(clazz);
criteria.add(Expression.eq(keyName, keyValue));
List l = criteria.list();
Full stack trace of any exception that occurs:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.purpleknot.ifb.core.client.bean.PKClientBean$PKClientPK.clientRef
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171)
at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:61)
at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:67)
at org.hibernate.tuple.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:98)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:307)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:158)
at org.hibernate.engine.EntityKey.generateHashCode(EntityKey.java:103)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:47)
at org.hibernate.engine.StatefulPersistenceContext.getCollectionOwner(StatefulPersistenceContext.java:644)
at org.hibernate.loader.Loader.readCollectionElement(Loader.java:980)
at org.hibernate.loader.Loader.readCollectionElements(Loader.java:635)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1919)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1676)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:454)
at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:755)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:229)
at org.hibernate.loader.Loader.doList(Loader.java:2145)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
at org.hibernate.loader.Loader.list(Loader.java:2024)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1533)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
at com.purpleknot.ifb.core.hibernate.HibernateUtils.get(HibernateUtils.java:48)
at com.purpleknot.ifb.core.client.access.hibernate.PkClientIntermediaryDAOImpl.getIntermediary(PkClientIntermediaryDAOImpl.java:46)
at com.purpleknot.ifb.core.client.access.hibernate.PkClientIntermediaryDAOImplTest.testGetIntermediaries(PkClientIntermediaryDAOImplTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:436)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:311)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:145)
... 45 more
Name and version of the database you are using:
DB2
The generated SQL (show_sql=true):
Hibernate:
select
this_.CLRFDG as CLRFDG0_0_,
this_.CLEFDG as CLEFDG0_0_,
this_.CLSQDG as CLSQDG0_0_,
this_.INRODG as INRODG0_0_,
this_.CLFNDG as CLFNDG0_0_,
this_.CLSNDG as CLSNDG0_0_,
this_.CLCNDG as CLCNDG0_0_
from
NFUDEV.CLTCEN this_
where
this_.CLRFDG=?
Hibernate:
select
intermedia0_.CLRFIK as CLRFIK1_,
intermedia0_.INRFIK as INRFIK1_,
pkclientde1_.CLRFDG as CLRFDG0_0_,
pkclientde1_.CLEFDG as CLEFDG0_0_,
pkclientde1_.CLSQDG as CLSQDG0_0_,
pkclientde1_.INRODG as INRODG0_0_,
pkclientde1_.CLFNDG as CLFNDG0_0_,
pkclientde1_.CLSNDG as CLSNDG0_0_,
pkclientde1_.CLCNDG as CLCNDG0_0_
from
NFUDEV.CLTINT intermedia0_
left outer join
NFUDEV.CLTCEN pkclientde1_
on intermedia0_.INRFIK=pkclientde1_.CLRFDG
where
intermedia0_.CLRFIK=?
|