-->
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.  [ 5 posts ] 
Author Message
 Post subject: saving and updating collection with self reference
PostPosted: Tue Dec 02, 2008 12:10 pm 
Newbie

Joined: Tue Dec 02, 2008 10:42 am
Posts: 3
Hi all

I've got two classes: self -referencing ClassB and ClassA which works as a wrapper.
Code:
ClassA{
public void ClassA(String nr){
this.nr=nr
}
private String nr;
...
private Set<ClassB> pr;
...
}

ClassB{
private String ID;
private String nr;
private String parentID;
private Set<ClassB> pr ;
...
}


db structure (MySql5) as follows:
Code:
CREATE TABLE A (
   Nr VARCHAR(20)  NOT NULL,
   PRIMARY KEY (Nr)
) ENGINE=InnoDB;

CREATE TABLE B (
   ID VARCHAR(40) NOT NULL,
   NrU VARCHAR(20)
   ParentID VARCHAR(40),
   PRIMARY KEY (ID)
) ENGINE=InnoDB;


and mapping:

Code:
<class name = "classA" table="A">
<id name="nr" type="string">
<column  name="Nr"/>
<generator class="assigned"/>
</id>
<set name="pr"  where="ParentID is null" cascade="all" lazy="false"  >
  <key column ="NrU"  />
  <one-to-many class="ClassB" />
  </set>
</class>


<class name = "ClassB" table="B">
   <id name="ID" type="string">
  <column  name="ID"/>
  <generator class="guid"/>
  </id>
  <property name="nr" column="NrU"   />
  <property name="parentID" column="ParentID" not-null="false" /> 
  <set cascade="all" lazy="false" name="pr"  table="B" >
   <key>
   <column name="ParentID" not-null="true"/>
   </key>
   <one-to-many class="ClassB" />
  </set>
</class>


I use Spring HibernateDaoSupport .There are no problems with persisting new objects of ClassA with embedded instances of ClassB. Data structure looks then as follows:

table A
Nr |
7777|

table B
ID|NrU|ParentID|
556886ea-11...|7777|null|
5568834a-11...|7777||556886ea-11...
5568814a-11...|7777||556884ea-11...

which is correct.

Trouble begins when there are no ClassB (table B) records and I try to update existing ClassA instance with new Set<ClassB>, eg

Code:
ClassA a = new ClassA("7777");  // I'm not retrieving this from db purposely
ClassB b = new ClassB("7777");
ClassB bb = new ClassB("7777");
b.getPr().add(bb);
a.getPr().add.(b);

getHibernateTemplate.saveOrUpdate(a);


after that database contains following records:

table B
table B
ID|NrU|ParentID|
556886ea-11...|7777|null|
5568834a-11...|null||556886ea-11...
5568814a-11...|null||556884ea-11...

There are missing NrU values in database. Only root contains NrU value, for other rows NrU == null.

Of course, when I retrieve existing ClassA from database and perform the same oerations, result is successfull.

Is there any way to perform such a update in a way I described ? Or maybe better take same other aproach ?

thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 1:13 pm 
Beginner
Beginner

Joined: Wed Nov 19, 2008 8:25 am
Posts: 46
Location: Saint Petersburg, Russian Federation
I'm afraid your problem is unclear. Am I right assuming that you execute the following code

Code:
ClassA a = new ClassA("7777");
ClassB b = new ClassB("7777");
ClassB bb = new ClassB("7777");
b.getPr().add(bb);
a.getPr().add.(b);


and the question is why there is the only row with not null 'NrU' value at B table? If so, the answer is that it functions as designed because ClassA object references the single ClassB object.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 5:07 pm 
Newbie

Joined: Tue Dec 02, 2008 10:42 am
Posts: 3
Quote:
and the question is why there is the only row with not null 'NrU' value at B table?.


Yes, that's my question.

To be more clear, let's discuss two cases.

1. Clean database, no records in table A, neither in table B.
Code:

ClassA a = new ClassA("7777");
ClassB b = new ClassB("7777");
ClassB bb = new ClassB("7777");
b.getPr().add(bb);
a.getPr().add.(b);
getHibernateTemplate.saveOrUpdate(a);

result database content :
Code:
table A
Nr |
7777|

table B
ID|NrU|ParentID|
556886ea-11...|7777|null|
5568834a-11...|7777||556886ea-11...
5568814a-11...|7777||556884ea-11...

And this behaviour is ok from my point of view. As you said, ClassA references single ClassB object, which is the root of ClassB type nodes tree.

2.Table A contains one record, which refers to saved instance of ClassA. Table B is empty, what is interpreted as no tree of ClassB type nodes joined with ClassA object.

Code:
table A
Nr |
7777|

table B
ID|NrU|ParentID


then I execute the same code to add tree of ClassB object to ClassA object.
Code:
ClassA a = new ClassA("7777");
ClassB b = new ClassB("7777");
ClassB bb = new ClassB("7777");
b.getPr().add(bb);
a.getPr().add.(b);
getHibernateTemplate.saveOrUpdate(a);

and the result is:
Code:
tableA
Nr |
7777|

table B
ID|NrU|ParentID|
556886ea-11...|7777|null|
5568834a-11...|null||556886ea-11...
5568814a-11...|null||556884ea-11...

which is wrong, becase of missing NrU values. Only first row, which refers to root element of the tree , contains proper NrU value.
The question is : is it mapping problem, or not ? Maybe I missed some steps during updating persistent objects ?

thanks


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 8:05 am 
Beginner
Beginner

Joined: Wed Nov 19, 2008 8:25 am
Posts: 46
Location: Saint Petersburg, Russian Federation
    *) only two rows (not three) appear at the B after the mentioned code snippet execution;
    *) the problem is not at the second use-case, the first one behaves incorrectly - hibernate is object-relational mapping framework, i.e. data to store is defined at the OO level. Only single ClassB object is referenced from the ClassA object, hence, there should be the only record at the B with not null 'NrU' value;
    *) the reason of the incorrect behavior mentioned previously is incorrect mapping. You map 'ClassB.nr' either as a foreign key at the entity collection mapping or as a ClassB persistent property. That property should be removed from the ClassB and its mapping metadata, everything works as expected then (B record has not null 'NrU' value only if corresponding object is referenced from the ClassA object). If you need to have a bidirectional association you should define ClassA as a type of the 'ClassB.nr' property and change mapping metadata accordingly;


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 04, 2008 9:11 am 
Newbie

Joined: Tue Dec 02, 2008 10:42 am
Posts: 3
Quote:
*) only two rows (not three) appear at the B after the mentioned code snippet execution;


Yes, that's my mistake. I've pasted it from other test case.


Finally, I solved problem by adding to database new field B.ParentA and replacing it as a foreign key in colection mapping in ClassA:

Code:
<class name = "ClassA" table="A">
...
<set name="pr"  where="ParentID is null" cascade="all" lazy="false"  >
  <key column ="ParentA"  />
  <one-to-many class="ClassB" />
</set>
</class>

<class name ="ClassB"  table="B">
..
<property name="nr" column="NrU"   />
..
</class>
.
.


Now it's possible to set and get nr property at any node of persisted tree of ClassB object. Maybe not the most elegant solution, but it works.

Thanks for help


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.