Hibernate version: 3
Name and version of the database you are using: Oracle 10g
Hi,
I'm having trouble with saving a set of associations, that contains data from a table PARENT and a table CHILD (CHILD inherits PARENT)
CHILD and PARENT are linked by an association table ASSOCIATION
Mapping documents:
#######
PARENT
#######
<hibernate-mapping>
<class name="path.Parent" table="PARENT" schema="S">
<!-- Generate an abstract class with protected class variables -->
<meta attribute="generated-class">path.gen.ParentGen</meta>
<meta attribute="scope-class" inherit="false">public abstract</meta>
<meta attribute="scope-field">protected</meta>
<id name="parentId" type="long">
<column name="PARENT_ID" precision="10" scale="0" />
<generator class="sequence">
<param name="sequence">S.PARENT_ID</param>
</generator>
</id>
<version name="version" column="VERSION" />
<my properties...>
<my sets and many-to-many associations...>
<set name="parentAssociations" inverse="true" >
<key>
<column name="PARENT_ID_PARENT" precision="10" scale="0" not-null="true" />
</key>
<one-to-many class="path.Association" />
</set>
</class>
</hibernate-mapping>
######
CHILD
######
<hibernate-mapping>
<joined-subclass name="path.Child" table="CHILD" schema="S" extends="path.Parent" >
<!-- Generate an abstract class with protected class variables -->
<meta attribute="generated-class">path.gen.ChildGen</meta>
<meta attribute="scope-class" inherit="false">public abstract</meta>
<meta attribute="scope-field">protected</meta>
<key column="PARENT_ID" />
<my properties...>
<set name="childAssociations" inverse="true">
<key>
<column name="PARENT_ID_CHILD" precision="10" scale="0" not-null="true" />
</key>
<one-to-many class="path.Association" />
</set>
</joined-subclass>
</hibernate-mapping>
###########
ASSOCIATION
###########
<hibernate-mapping>
<class name="path.Association" table="ASSOCIATION" schema="S">
<!-- Generate an abstract class with protected class variables -->
<meta attribute="generated-class">path.gen.AssociationGen</meta>
<meta attribute="scope-class" inherit="false">public abstract</meta>
<meta attribute="scope-field">protected</meta>
<composite-id name="id" class="path.Association$PK">
<key-property name="parentId" column="PARENT_ID_PARENT" type="long" />
<key-property name="childId" column="PARENT_ID_CHILD" type="long" />
</composite-id>
<version name="version" column="VERSION" />
<my properties...>
<many-to-one name="parent" class="path.Parent" update="false" insert="false" not-null="true" >
<column name="PARENT_ID_PARENT" />
</many-to-one>
<many-to-one name="child" class="path.Child" update="false" insert="false" not-null="true" >
<column name="PARENT_ID_CHILD" />
</many-to-one>
</class>
</hibernate-mapping>
here is the DB scheme : [img=http://img468.imageshack.us/img468/9181/fullschema1lj.th.png]
##################
I have only one DAO for the parent, which works correctly for associations, excepted the one which link CHILD and PARENT.
Does this case require a specific mapping ???
So, in my test, I first create a child, and add properties to it, I save it in the DB... and then create a new <Association>set, add it to the child, and then save again.
We force the commit to be sure that insertion is done
###################
public void testMyAssociation() {
ParentDAO dao = (ParentDAO)applicationContext.getBean("parentDAO");
Session session = ((SessionFactory)applicationContext.getBean("sessionFactory")).getCurrentSession();
Transaction tr = session.beginTransaction();
// create a Child and populate it
Child child = new Child();
TestCaseUtil.populatePOJO(child, "parentId");
assertNull(child.getParentId()); // test OK
// save Child using parent DAO (thanks to inheritance) before adding it a set
dao.saveParent(child);
assertNotNull(child.getParentId()); // test OK
/* create an <Association>Set of size 3 that will be like
* row 1 : child - parent1
* row 2 : child - parent2
* row 3 : child - parent3
*/
Parent parent1 = new Parent();
Parent parent2 = new Parent();
Parent parent3 = new Parent();
// create the 3 associations via constructor
Association association = new Association(child, parent1);
association = new Association(child, parent2);
association = new Association(child, parent3);
// test on last association created OK
logger.debug(association.getId().getParentId);
logger.debug(association.getId().getChildId);
dao.saveParent(child);
session.flush();
tr.commit();
}
#####################
Everything if fine, the tests work,the child object is save but the <Association>set is not
when I create an Association, values are added to child childAssociations and parentAssociations set.
here is the code for the association class
NB: AssociationGen contains all getters and setters methods, nothing more
######################
public class Association extends AssociationGen {
public static final long serialVersionUID = 1000012L;
// ******************* Inner composite PK class ******************* //
public static class PK implements Serializable {
public static final long serialVersionUID = 1000013L;
private Long parentId;
private Long childId;
/*
* inner class constructors
*/
public PK() {}
public PK(Long parentId, Long childId) {
this.parentId = parentId;
this.childId=childId;
}
/*
* getters and setters
*/
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public Long getChildId() {
return childId;
}
public void setChildId(Long childId) {
this.childId = childId;
}
/*
*
*/
public boolean equals(Object o) {
if (o instanceof PK) {
PK that = (PK) o;
return this.parentId.equals(that.parentId) && this.childId.equals(that.childId);
} else {
return false;
}
}
public int hashCode() {
return parentId.hashCode() + childId.hashCode();
}
}
// ******************* End Inner composite PK class ******************* //
/*
* class constructors
*/
public Association() {
super();
this.id = new PK();
}
public Association(Parent parent, Child child) {
this();
this.parent = parent;
this.child = child;
// Set key values
this.id.parentId = parent.getParentId();
this.id.childId= child.getParentId();
// Guarantee referential integrity
if (parent.getParentAssociations() == null) {
parent.setParentAssociations(new HashSet());
}
if (child.getChildAssociations() == null) {
child.setChildAssociations(new HashSet());
}
parent.setParentAssociations().add(this);
child.setChildAssociations().add(this);
}
/*
*
*/
public String toString() {
return overrideToStringMethod(this);
}
}
###################
At this time, I check each line of code, reading it a thousand time, and I really don't know, why, with this kind of association, saving a set doesn't work. Any help would be good.
I worked on a DB scheme of 100 tables (we modelise biological environement), and I have problem only with this case, which is the only one with such a mapping.
Thanks for any help