I've got two tables, TableParent and TableChild:
Code:
+---------------+ +----------------+
| TableParent | | TableChild |
+---------------+ +----------------+
| Composed PK |-------------| Composed PK/FK |
| Key PK | | Key PK/FK |
| Attribute | | ChildAttribute |
+---------------+ +----------------+
As you can see, TableChild's primary key is the foreign key from TableParent.
I guess I
should have made a mapping file describing this as TableChild
extending TableParent, but I didn't, in stead I defined this as a one-to-one mapping:
TableParent.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<class
name="error.demo.hibernate.composite_keys.model.TableParent"
table='"TableParent"'
>
<meta attribute="implement-equals" inherit="false">true</meta>
<composite-id name="comp_id" class="error.demo.hibernate.composite_keys.model.TableParentPK">
<key-property
name="composed"
column="Composed"
type="long"
length="10"
/>
<key-property
name="key"
column="Key"
type="long"
length="10"
/>
</composite-id>
<property
name="attribute"
type="java.lang.Long"
column="Attribute"
length="10"
/>
<one-to-one
name="tableChild"
class="error.demo.hibernate.composite_keys.model.TableChild"
outer-join="auto"
/>
</class>
</hibernate-mapping>
TableChild.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<class
name="error.demo.hibernate.composite_keys.model.TableChild"
table='"TableChild"'
>
<meta attribute="implement-equals" inherit="false">true</meta>
<composite-id name="comp_id" class="error.demo.hibernate.composite_keys.model.TableChildPK">
<key-property
name="composed"
column="Composed"
type="long"
length="10"
/>
<key-property
name="key"
column="Key"
type="long"
length="10"
/>
</composite-id>
<property
name="childAttribute"
type="java.lang.String"
column="ChildAttribute"
length="19"
/>
<one-to-one
name="tableParent"
class="error.demo.hibernate.composite_keys.model.TableParent"
outer-join="auto"
constrained="true"
/>
</class>
</hibernate-mapping>
So far so good, no complaints when configuring hibernate. But if I manually insert a row in TableParent and TableChild, and ask hibernate to load this row, using
Code:
TableParentPK pk = new TableParentPK(1,2);
TableParent pi = (TableParent) s.load(TableParent.class, pk);
I get an ugly ClassCastException, deep down in CGLIB:
Code:
Exception in thread "main" java.lang.RuntimeException: net.sf.hibernate.PropertyAccessException: exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) getter of error.demo.hibernate.composite_keys.model.TableParentPK.?
at error.demo.hibernate.composite_keys.CompositeKeyErrorDemo.main(CompositeKeyErrorDemo.java:41)
Caused by: net.sf.hibernate.PropertyAccessException: exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) getter of error.demo.hibernate.composite_keys.model.TableParentPK.?
at net.sf.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:193)
at net.sf.hibernate.type.ComponentType.nullSafeGetValues(ComponentType.java:164)
at net.sf.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:151)
at net.sf.hibernate.loader.Loader.bindPositionalParameters(Loader.java:753)
at net.sf.hibernate.loader.Loader.prepareQueryStatement(Loader.java:793)
at net.sf.hibernate.loader.Loader.doQuery(Loader.java:269)
at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:138)
at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:941)
at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:961)
at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:59)
at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:51)
at net.sf.hibernate.persister.EntityPersister.load(EntityPersister.java:413)
at net.sf.hibernate.impl.SessionImpl.doLoad(SessionImpl.java:2131)
at net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:2001)
at net.sf.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1963)
at net.sf.hibernate.type.OneToOneType.resolveIdentifier(OneToOneType.java:71)
at net.sf.hibernate.type.EntityType.resolveIdentifier(EntityType.java:208)
at net.sf.hibernate.impl.SessionImpl.initializeEntity(SessionImpl.java:2219)
at net.sf.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:319)
at net.sf.hibernate.loader.Loader.doQuery(Loader.java:309)
at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:138)
at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:941)
at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:961)
at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:59)
at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:51)
at net.sf.hibernate.persister.EntityPersister.load(EntityPersister.java:413)
at net.sf.hibernate.impl.SessionImpl.doLoad(SessionImpl.java:2131)
at net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:2001)
at net.sf.hibernate.impl.SessionImpl.load(SessionImpl.java:1930)
at error.demo.hibernate.composite_keys.CompositeKeyErrorDemo.main(CompositeKeyErrorDemo.java:39)
Caused by: java.lang.ClassCastException
at error.demo.hibernate.composite_keys.model.TableParentPK$$BulkBeanByCGLIB$$6222dd4a.getPropertyValues(<generated>)
at net.sf.cglib.beans.BulkBean.getPropertyValues(BulkBean.java:86)
at net.sf.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:190)
... 29 more
If I replace the TableChildPK with a TableParentPK, then it works, but shouldn't this work as well? (the mapping files were originally generated by middlegen, that's why the PK classes are two separate classes in the first place)
Hibernate version: 2.1.8
Eivind