Hi,
I am trying to perform a simple example for a many to many association.
My two classes are Zone and ZoneSet and the class representing the association is ZoneToZoneSet.
As advised in the book "Java persistence with Hibernate", I am using a composite id for the association table (ZoneToZoneSet) id. The ZoneToZoneSet class then declares an inner class to handle the composite id. The composite id is of course made up of the id from ZoneSet and the id from Zone.
When using a composite id, one should not specify getter and setter methods for the id since hibernate gets the values directly.
However when I do not specify accessors for the id, I get the following error at run time: (Hibernate 3.2.5 ga), which indicates that a getter is needed:
Code:
org.hibernate.PropertyNotFoundException: Could not find a getter for id in class test.ZoneToZoneSet
at org.hibernate.property.BasicPropertyAccessor.createGetter(BasicPropertyAccessor.java:282)
at org.hibernate.property.BasicPropertyAccessor.getGetter(BasicPropertyAccessor.java:275)
at org.hibernate.tuple.PropertyFactory.getGetter(PropertyFactory.java:168)
at org.hibernate.tuple.PropertyFactory.buildIdentifierProperty(PropertyFactory.java:44)
at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:123)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:434)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:109)
at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:226)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
at test.Tester.getSessionFactory(Tester.java:35)
at test.Tester.testZones(Tester.java:41)
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:597)
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:130)
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)
This in itself suggests that there is a problem with my mappings / classes.
If I ignore this and implement dummy accessors for the id, I get one step further but I then get the following error :
Code:
java.lang.ClassCastException: java.lang.String
at org.hibernate.type.ComponentType.toLoggableString(ComponentType.java:377)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:112)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
at test.Tester.testZones(Tester.java:54)
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:597)
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:130)
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)
I don't believe that the second error is too significant as it is only there as a result of the first one.
Any help would be much appreciated.
Below is the code for my project:
ZoneToZoneSet.hbm.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">
<!-- Generated 23-Apr-2008 15:18:30 by Hibernate Tools 3.2.0.CR1 -->
<hibernate-mapping>
<class name="test.ZoneToZoneSet" table = "TSGZoneToZoneSet">
<composite-id name="id" class="test.ZoneToZoneSet$Id">
<key-property name="zoneSetId"
access="field"
column="ZONESET_ID"
length="32"
type="string"/>
<key-property name="zoneId"
access="field"
column="ZONE_ID"
length="32"
type="string"/>
</composite-id>
<many-to-one name="zoneSet"
column="ZONESET_ID"
not-null="true"
insert="false"
update="false"/>
<many-to-one name="zone"
column="ZONE_ID"
not-null="true"
insert="false"
update="false"/>
</class>
</hibernate-mapping>
ZoneSet.hbm.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">
<!-- Generated 23-Apr-2008 15:18:30 by Hibernate Tools 3.2.0.CR1 -->
<hibernate-mapping>
<class name="test.ZoneSet" table = "TSGZoneSet">
<id name="id" >
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="label" >
<column name="LABEL" length="128" />
</property>
<bag name="zonesToZoneSets" inverse="true" >
<key column="ZONESET_ID" />
<one-to-many class="test.ZoneToZoneSet" />
</bag>
</class>
</hibernate-mapping>
Zone.hbm.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">
<!-- Generated 23-Apr-2008 15:18:30 by Hibernate Tools 3.2.0.CR1 -->
<hibernate-mapping>
<class name="test.Zone" table = "TSGZone">
<id name="id" >
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="label" >
<column name="LABEL" length="128" />
</property>
<bag name="zonesToZoneSets" inverse="true" >
<key column="ZONE_ID" />
<one-to-many class="test.ZoneToZoneSet" />
</bag>
</class>
</hibernate-mapping>
ZoneToZoneSet.java
Code:
package test;
import java.io.Serializable;
public class ZoneToZoneSet {
@SuppressWarnings("serial")
public static class Id implements Serializable {
private String zoneSetId;
private String zoneId;
public Id() {}
public Id(String zoneSetId, String zoneId) {
this.zoneSetId = zoneSetId;
this.zoneId = zoneId;
}
public boolean equals(Object o) {
if (o != null && o instanceof Id) {
Id that = (Id)o;
return this.zoneId.equals(that.zoneId) &&
this.zoneSetId.equals(that.zoneSetId);
} else {
return false;
}
}
public int hashCode() {
return zoneSetId.hashCode() + zoneId.hashCode();
}
}
/**
* The Composite Id object
*/
protected Id id = new Id();
public String getId (){
return "someID";
}
public void setId (String id){
}
public ZoneToZoneSet() {
//id = new Id();
}
public ZoneToZoneSet(ZoneSet zoneSet, Zone zone) {
this();
// Set fields
this.zoneSet = zoneSet;
this.zone = zone;
// Set identifier values
((Id)this.id).zoneSetId = zoneSet.getId();
((Id)this.id).zoneId = zone.getId();
// Guarantee referential integrity
zoneSet.getZonesToZoneSets().add(this);
zone.getZonesToZoneSets().add(this);
}
/**
*/
private ZoneSet zoneSet;
/**
* Getter of the property <tt>zoneSet</tt>
* @return Returns the zoneSet.
*/
public ZoneSet getZoneSet() {
return zoneSet;
}
/**
* Setter of the property <tt>zoneSet</tt>
* @param zoneSet The zoneSet to set.
*/
public void setZoneSet(ZoneSet zoneSet) {
this.zoneSet = zoneSet;
}
/**
*/
private Zone zone = null;
/**
* Getter of the property <tt>zone</tt>
* @return Returns the zone.
*/
public Zone getZone() {
return zone;
}
/**
* Setter of the property <tt>zone</tt>
* @param zone The zone to set.
*/
public void setZone(Zone zone) {
this.zone = zone;
}
}
ZoneSet.java
Code:
package test;
import java.util.List;
public class ZoneSet {
/**
*/
private String id = null;
/**
* Getter of the property <tt>id</tt>
*/
public String getId() {
return id;
}
/**
* Setter of the property <tt>id</tt>
* @param id The id to set.
*/
protected void setId(String id) {
this.id = id;
}
/**
*/
private String label = null;
/**
* Getter of the property <tt>name</tt>
* @return Returns the name.
*/
public String getLabel() {
return label;
}
/**
* Setter of the property <tt>name</tt>
* @param name The name to set.
*/
public void setLabel(String label) {
this.label = label;
}
/**
*/
private List<ZoneToZoneSet> zonesToZoneSets = new java.util.ArrayList<ZoneToZoneSet>();
/**
* Getter of the property <tt>zonesToZoneSets</tt>
* @return Returns the zonesToZoneSets.
*/
public List<ZoneToZoneSet> getZonesToZoneSets() {
return zonesToZoneSets;
}
/**
* Setter of the property <tt>zonesToZoneSets</tt>
* @param zonesToZoneSets The zonesToZoneSets to set.
*/
public void setZonesToZoneSets(List<ZoneToZoneSet> zonesToZoneSets) {
this.zonesToZoneSets = zonesToZoneSets;
}
}
Zone.java
Code:
package test;
import java.util.List;
public class Zone {
/**
*/
private String id = null;
/**
* Getter of the property <tt>id</tt>
* @return Returns the id.
*/
public String getId() {
return id;
}
/**
* Setter of the property <tt>id</tt>
* @param id The id to set.
*/
protected void setId(String id) {
this.id = id;
}
/**
*/
private String label = null;
/**
* Getter of the property <tt>name</tt>
* @return Returns the name.
*/
public String getLabel() {
return label;
}
/**
* Setter of the property <tt>name</tt>
* @param name The name to set.
*/
public void setLabel(String label) {
this.label = label;
}
/**
*/
private List<ZoneToZoneSet> zonesToZoneSets = new java.util.ArrayList<ZoneToZoneSet>();
/**
* Getter of the property <tt>zonesToZoneSets</tt>
* @return Returns the zonesToZoneSets.
*/
public List<ZoneToZoneSet> getZonesToZoneSets() {
return zonesToZoneSets;
}
/**
* Setter of the property <tt>zonesToZoneSets</tt>
* @param zonesToZoneSets The zonesToZoneSets to set.
*/
public void setZonesToZoneSets(List<ZoneToZoneSet> zonesToZoneSets) {
this.zonesToZoneSets = zonesToZoneSets;
}
}
And finally the Tester:
Tester.java
Code:
package test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Tester extends TestCase {
private static SessionFactory factory= null;
private SessionFactory getSessionFactory (){
if (factory != null)
return factory;
Properties props = new Properties ();
try {
InputStream is = this.getClass().getResourceAsStream("hibernate.properties");
props.load(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
SessionFactory sessionFactory = new Configuration().addProperties(props).configure().buildSessionFactory();
return sessionFactory;
}
public void testZones (){
Session session = getSessionFactory ().openSession();
Transaction tx = session.beginTransaction();
Zone zone = new Zone ();
session.persist(zone);
ZoneSet zoneSet = new ZoneSet ();
session.persist(zoneSet);
ZoneToZoneSet zoneToZoneSet = new ZoneToZoneSet(zoneSet,zone);
session.persist(zoneToZoneSet);
tx.commit();
session.close();
}
}