I am using hibernate mapping files to map a couple of classes - twice. I have 2 classes: Event and SubEvent. SubEvent is a child of Event. I am having an issue with the mappings that are using a composite foreign key. When attempting to persist, I am consistently getting an exception with the message:
Quote:
object is not an instance of declaring class
-- More information provided below.
My java classes look like this:
Code:
public class Event implements Serializable
{
private static final long serialVersionUID = 129372632456748684L;
private String eventId;
private int version;
private String title;
private Date date;
private List<SubEvent> subEvents;
public Event() {}
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getVersion()
{
return version;
}
public void setVersion(int version)
{
this.version = version;
}
public List<SubEvent> getSubEvents()
{
return subEvents;
}
public void setSubEvents(List<SubEvent> subEvents)
{
this.subEvents = subEvents;
}
}
and SubEvent:
Code:
public class SubEvent implements Serializable
{
private static final long serialVersionUID = 404876620876665712L;
private String subEventId;
private String subEventName;
private Event parent;
public String getSubEventId()
{
return subEventId;
}
public void setSubEventId(String subEventId)
{
this.subEventId = subEventId;
}
public String getSubEventName()
{
return subEventName;
}
public void setSubEventName(String subEventName)
{
this.subEventName = subEventName;
}
public Event getParent()
{
return parent;
}
public void setParent(Event parent)
{
this.parent = parent;
}
}
I have two mapping files for the Event class:
Event.xml:
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">
<hibernate-mapping>
<class name="com.foo.jpa.hibernate.Event" table="EVENTS">
<id name="eventId" column="event_id" type="string"/>
<property name="version" column="version" type="int"/>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
<bag name="subEvents" cascade="all" lazy="false">
<key>
<column name="event_id" not-null="true"/>
</key>
<one-to-many class="com.foo.jpa.hibernate.SubEvent"/>
</bag>
</class>
</hibernate-mapping>
And the other mapping file:
EventHistory.xml:
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">
<hibernate-mapping>
<class name="com.foo.jpa.hibernate.Event" table="EVENTS_HISTORY">
<composite-id>
<key-property name="eventId" column="event_id" type="string" length="36"/>
<key-property name="version" column="version" type="int"/>
</composite-id>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title" type="string" length="200"/>
<bag name="subEvents" cascade="all" lazy="false">
<key>
<column name="event_id" not-null="true"/>
<column name="version" not-null="true"/>
</key>
<one-to-many class="com.foo.jpa.hibernate.SubEvent"/>
</bag>
</class>
</hibernate-mapping>
SubEvent also has two mappings:
SubEvent.xml:
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">
<hibernate-mapping>
<class name="com.foo.jpa.hibernate.SubEvent" table="SUB_EVENTS">
<id name="subEventId" column="sub_event_id" type="string"/>
<many-to-one name="parent" cascade="all" class="com.foo.jpa.hibernate.Event" lazy="false" column="event_id" not-null="true"/>
<property name="subEventName" column="sub_event_name" type="string"/>
</class>
</hibernate-mapping>
And SubEventHistory.xml:
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">
<hibernate-mapping>
<class name="com.foo.jpa.hibernate.SubEvent" table="SUB_EVENTS_HISTORY">
<id name="subEventId" column="sub_event_id" type="string"/>
<many-to-one name="parent" cascade="all" class="com.foo.jpa.hibernate.Event" lazy="false">
<column name="event_id" not-null="true"/>
<column name="version" not-null="true"/>
</many-to-one>
<property name="subEventName" column="sub_event_name" type="string"/>
</class>
</hibernate-mapping>
I am persisting events (with children subevents) and event histories (with children subevent histories) using 2 sessions.
I'm using the hibernate entity manager for persistence. My persistence.xml looks like this:
Code:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="PU_TEST1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>Event.xml</mapping-file>
<mapping-file>SubEvent.xml</mapping-file>
<properties>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:medclaimdb"/>
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
</properties>
</persistence-unit>
<persistence-unit name="PU_TEST2" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>EventHistory.xml</mapping-file>
<mapping-file>SubEventHistory.xml</mapping-file>
<properties>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:medclaimdb"/>
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
</properties>
</persistence-unit>
</persistence>
My persistence code looks similar to this:
Code:
// factory1 is associated with PU_TEST1
// factory 2 is associated with PU_TEST2
// Find the event.
EntityManager em1 = factory1.createEntityManager();
Event event = em1.find(Event.class, id);
em1.close();
// persist the history
EntityManager em2 = factory2.createEntityManager();
em2.getTransaction.begin();
// This line throws an exception!
em2.persist(event);
em2.getTransaction.commit();
em2.close();
// remove the event.
em1 = factory1.createEntityManager();
em1.getTransaction.begin();
em1.remove(event);
em1.getTransaction.commit();
em1.close();
As noted above, the line "em2.persist(event)" is throwing an exception. The stack is posted below:
Code:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.foo.jpa.hibernate.Event.eventId
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:226)
at com.foo.jpa.hibernate.EventService.deleteEvent(EventService.java:61)
at com.foo.jpa.hibernate.EventServiceTest.testDelete(EventServiceTest.java:56)
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:585)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
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.foo.jpa.hibernate.Event.eventId
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:195)
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:87)
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:93)
at org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:109)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:376)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:207)
at org.hibernate.engine.CollectionKey.generateHashCode(CollectionKey.java:78)
at org.hibernate.engine.CollectionKey.<init>(CollectionKey.java:66)
at org.hibernate.engine.CollectionKey.<init>(CollectionKey.java:52)
at org.hibernate.engine.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:786)
at org.hibernate.engine.StatefulPersistenceContext.addInitializedDetachedCollection(StatefulPersistenceContext.java:823)
at org.hibernate.event.def.ProxyVisitor.reattachCollection(ProxyVisitor.java:88)
at org.hibernate.event.def.WrapVisitor.processCollection(WrapVisitor.java:68)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
at org.hibernate.event.def.WrapVisitor.processValue(WrapVisitor.java:121)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:78)
at org.hibernate.event.def.AbstractSaveEventListener.visitCollectionsBeforeSave(AbstractSaveEventListener.java:394)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:296)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:154)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:110)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:645)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:619)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:623)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220)
... 24 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(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:169)
... 51 more
As I said above, I really think this has something to do with the fact that the EventHistory.xml and SubEventHistory.xml uses a composite foreign key. When I removed the composite foreign key and simply used eventId as the foreign key, the code worked as expected. If anyone has any advice for me on what could be causing this I would greatly appreciate it, or if there is a better way to accomplish this same result. I'm not very familiar with using the hibernate mapping files. I was able to successfully use a composite foreign key as described above using JPA annotations (using @OneToMany and @ManyToOne annotations) and now that I am trying to switch over to hibernate mapping files I cannot get past this issue. Oh and before I forget, I am using
hibernate-entitymanager-3.4.0.GA. Thanks in advance!