Hibernate version: 3.2.2.ga
Mapping documents:
Code:
<hibernate-mapping auto-import="true" default-cascade="all-delete-orphan" >
<class name="com.test.compositeId.Parent" >
<composite-id name="key" class="com.test.compositeId.CompoundKey">
<key-property name="id" type="java.lang.Long" >
<column name="parent_id" not-null="true"/>
</key-property>
<key-property name="version" type="java.lang.Long" >
<column name="parent_version_nr" not-null="true"/>
</key-property>
</composite-id>
<map name="children" cascade="all">
<key on-delete="noaction" not-null="true">
<column name="parent_id" />
<column name="parent_version_nr" />
</key>
<map-key type="string">
<column name="parent_role" not-null="true" />
</map-key>
<one-to-many class="com.test.compositeId.Child" embed-xml="true" not-found="exception" />
</map>
</class>
</hibernate-mapping>
<hibernate-mapping auto-import="true" default-cascade="all-delete-orphan" >
<class name="com.test.compositeId.Child" >
<composite-id name="key" class="com.test.compositeId.CompoundKey">
<key-property name="id" type="java.lang.Long" >
<column name="child_id" not-null="true"/>
</key-property>
<key-property name="version" type="java.lang.Long" >
<column name="child_version_nr" not-null="true"/>
</key-property>
</composite-id>
<many-to-one name="parent" class="com.test.compositeId.Parent"
unique="true" not-null="true" insert="false" update="false" >
<column name="parent_id"/>
<column name="parent_version_nr"/>
</many-to-one>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
public class TestOneToMany extends TestCase {
public void testOneToMany() throws Exception {
Configuration config = new Configuration().configure("hibernate.test.compositeId.cfg.xml");
SessionFactory sessionFactory = config.buildSessionFactory();
Parent parent = new Parent();
Child child = new Child();
Map children = new HashMap();
children.put("child1", child);
parent.setChildren(children);
child.setParent(parent);
parent.setKey(new CompoundKey(1,1));
child.setKey(new CompoundKey(1,1));
Session s = sessionFactory.openSession(new EntityInterceptor());
Transaction tx = s.beginTransaction();
boolean ok=false;
try {
s.saveOrUpdate(parent);
tx.commit();
ok=true;
} catch (Exception e) {
throw new IllegalStateException("unexpected problem on saving", e);
} finally {
try {
if (!s.connection().isClosed()) {
if (!ok)
tx.rollback();
s.close();
}
} catch (Exception e) {
throw new IllegalStateException("problem tidying up session");
}
}
}
}
[/c
Full stack trace of any exception that occurs:
java.lang.IllegalStateException: unexpected problem on saving
at com.test.compositeId.TestOneToMany.testOneToMany(TestOneToMany.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
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.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.test.compositeId.CompoundKey.id
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171)
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:64)
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:70)
at org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:83)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:353)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:348)
at org.hibernate.engine.Cascade.cascadeComponent(Cascade.java:193)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:179)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:431)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:265)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:334)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at com.test.compositeId.TestOneToMany.testOneToMany(TestOneToMany.java:38)
... 18 more
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(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:145)
... 57 more
Oracle 9.2.0.7:
The generated SQL (show_sql=true):
Hibernate: select parent_.parent_id, parent_.parent_version_nr from PARENT_COMPOSITE_ID parent_ where parent_.parent_id=? and parent_.parent_version_nr=?
Hibernate: select child_.child_id, child_.child_version_nr from CHILD_COMPOSITE_ID child_ where child_.child_id=? and child_.child_version_nr=?
06-Feb-2007 16:21:19 org.hibernate.property.BasicPropertyAccessor$BasicGetter get
SEVERE: IllegalArgumentException in class: com.test.compositeId.CompoundKey, getter method of property: id
Extra Information:
I get the above exception, when I try to save a Parent object.
On debugging through the testcase, the exception occurs as the getId() method on CompoundKey is being invoked on a BackrefPropertyAccessor object.
I have tried mapping the classes with an id element rather than a composite-id element and the test passes. But unfortunately I am working with a database schema that has composite keys, is there another way to map this?
By setting the default-cascade property on the hibernate-mapping element to none, the test case works. But only once, i.e. for inserts only, I get the same exception when I try to update a record.
I would be very grateful for any help on this.
Thanks.