-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: complex mapping and saving set
PostPosted: Fri Oct 28, 2005 5:59 am 
Newbie

Joined: Fri Oct 28, 2005 4:30 am
Posts: 16
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


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 28, 2005 6:40 am 
Beginner
Beginner

Joined: Thu Jan 22, 2004 8:22 pm
Posts: 48
I've never done a mapping exactly like this but I think I see your problem.

- One the set in parent that contains Associations you have inverse true which says that that set isn't used to manage the association. This means adding a object to this set does not trigger hibernate to do anything.

- On the set in Child you also have inverse true so that set is not used to manage anything.

This means Associations are never seen as associated with anything and you never explicitly save them so they don't get saved. I'm also wondering if update and insert false on the many-to-one links in Association might just make absolutely sure that these relationships are never persisted.

Having said all that I'm not sure I know which is the best way to correct the problem but I think you should remove the inverse and the update/insert attribbutes. You might also need to say cascade on the sets if you want the save of the Association to be automatic.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 28, 2005 8:35 am 
Newbie

Joined: Fri Oct 28, 2005 4:30 am
Posts: 16
Thank you so much !!! you helped me a lot, even if my problem is not due to inverse="true".
In fact, I saw by comparing with my other sets that the cascade attribute was missing. So there is no transitive persistence !!!
I just miss this attribute when I rewrote the mapping. As my DB is moving a lot I needed to rewrite some parts of my code. Argh !

So now my sets mappings look like this :

in parent :
<set name="parentAssociations" inverse="true" cascade="all-delete-orphan">
<key>
<column name="PARENT_ID_PARENT" precision="10" scale="0" not-null="true" />
</key>
<one-to-many class="path.Association" />
</set>

in child :
<set name="childAssociations" inverse="true" cascade="all-delete-orphan">
<key>
<column name="PARENT_ID_CHILD" precision="10" scale="0" not-null="true" />
</key>
<one-to-many class="path.Association" />
</set>

Many thanks again !!!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.