-->
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: object identities and cascading saves
PostPosted: Mon Jan 09, 2006 11:09 am 
Newbie

Joined: Tue Dec 28, 2004 12:12 am
Posts: 5
Hi I have a question about object identities and cascading saves.

As an example assume I have two classes:

Language which has two fields 'code' for example 'en' and 'name' for example 'English'
Code:
<hibernate-mapping package="domain">
   <class name="Language" table="pb_language">
      <id name="code" column="code" type="string" length="10">
         <generator class="assigned"/>
      </id>
      <property name="name"    type="string"    not-null="true" length="100"/>
   </class>
</hibernate-mapping>



Person which has a number of fields 2 related to Language, 'defaultLanguage' and
'languages'.
Code:
<hibernate-mapping package="domain">
   <class name="Person" table="pb_person">
      <id name="id" column="id" type="long">
         <generator class="native"/>
      </id>
      <property name="name"          type="string"    not-null="true" length="100"/>
      <many-to-one name="defaultLanguage" class="Language" not-null="true" cascade="save-update" />
      <set name="languages" table="pb_person_languages" cascade="save-update">
         <key column="person_id" />
         <many-to-many column="language_id" class="Language" />
      </set>
       
   </class>
</hibernate-mapping>


My application constructs a Person class with the associated Language objects. But I am having 2 problems:

1- if I specify that defaultLanguage is not-null then adding the person class fails with:
not-null property references a null or transient value: domain.Person.defaultLanguage
Note, that Person does have a defaultLanguage (ie it is not null).

2- if the default language is also in the languages set, adding fails telling me:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [domain.Language#en]

Perhaps I need to change my PersonDAO class to make sure it creates Language objects prior to trying to save a Person,
but I thought that was the use of cascade.

Perhaps I have messed up with identifiers, although I did override the equals, and hashcode methods of Language.

Most likely I have misunderstood something. I am hoping someone in this forum has gone through the same problem and
can offer me some advice.

Thanks,
Hani


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 09, 2006 11:47 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
When you want to set an existing language, you must load it into the session or get a link to the one exiting in the session.
transient means that your language is not yet saved and an ID is not created.

example:
language = session.get(1);
if (language == null) // it is transient
{
//set all needed fields
session.save(language);
0
person.getLanguages.add(language);
session.save(person);



Something else:
you may consider to use iso_codes instead of a integer primary key.

Regards Sebastian

Please rate, if this helped out.

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 09, 2006 12:10 pm 
Newbie

Joined: Tue Dec 28, 2004 12:12 am
Posts: 5
Thanks for the reply.

From your example it seems like my PersonDAO.add(Person person) method would need to check if defaultLanguage and languages have
been persisted prior to persisting Person. If that is the case than what
does the cascade="save-update" do? I thought the whole point was that
with cascading I could simply save the person object and the corresponding Language objects would be saved if needed.

Not sure what you meant by int identifiers, my Language object has a
String identifier (user assigned) called 'code'.

Hani

LaLiLuna wrote:
When you want to set an existing language, you must load it into the session or get a link to the one exiting in the session.
transient means that your language is not yet saved and an ID is not created.

example:
language = session.get(1);
if (language == null) // it is transient
{
//set all needed fields
session.save(language);
0
person.getLanguages.add(language);
session.save(person);



Something else:
you may consider to use iso_codes instead of a integer primary key.

Regards Sebastian

Please rate, if this helped out.


Top
 Profile  
 
 Post subject: Re: object identities and cascading saves
PostPosted: Mon Jan 09, 2006 1:15 pm 
Regular
Regular

Joined: Tue Nov 16, 2004 6:36 pm
Posts: 62
Location: Zürich
regarding 2: make sure you don't add two different instances in the Person class, i.e. one language as defaultLanguage and a different instance of the same language in the set. Otherwise you have (as the error message says) two different objects with the same identifier.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 09, 2006 1:15 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
This is partial right:

when you create a new language instance and a new person instance
and
add the language to your person and save the person than both will be saved if the cascase is properly set.
but:
as language has a defined id, you must be sure that you do not have allready have an instance in your session or in the database. The first case leeds to your exception 1, the second to duplicate key.

If you are unsure, you must look up if the language exists. I say this as I expect that you will generate languages in very rare cases.

You can only have one instance with the same primary key in the same session. session save will not look up an instance of your langauge in the session. session.save tries to regenerate a new instance in the session and will fail if one exist. So if the object may exist in the session than you should be sure that you get this instance or you will get your exception 2
session.get(Langauge.class,'en') will get you this instance.

Sebastian

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


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.