-->
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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Update Associate Objects - Default Behaviour of Hibernate ??
PostPosted: Tue Jun 26, 2007 1:40 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Wondering how update works in case of associated objects.
Let say if Parent object ( in my case DeviceType) is associated with 3 records of Child object ( in my case Role) .

During update, if i add or delete a Role from the User Interface, i have observed the default behaviour of Hibernate is to
"delete the exsisting records from association table and then insert updated records "

Wondering why Hibernate cant really do an update on intermediate table instead of delete & insert

Any pointers/suggestions will be highly appreciated


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 4:01 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
What are you cascade settings ?

Try cascade="save-update".

Regards,
Jitendra
*Please do rate if it helps*


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 4:26 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Yep i am already using cascade="save-update".


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 4:28 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Forgot to mention the actual setting is cascade="all,delete-orphan" so that i can have save, update & delete of associated objects


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 4:29 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Are you trying to do something like:
[url]
http://forum.hibernate.org/viewtopic.php?t=976731
[/url]

Please post your questions using the recomended format:
http://www.hibernate.org/ForumMailinglists/HowToAskForHelp for quicker resolution.

Regards,
Jitendra

*Please don't forget to rate if it helps*


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 6:51 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Thanks Jitendra for quick response.
I am certainly Not doing explicit remove/delete or insert as mentioned in http://forum.hibernate.org/viewtopic.php?t=976731 (i.e. parent.getChildren().remove(group);
parent.getChildren().add(group);
)

Its the Hibernate which does the delete & insert when i call hibernateTemplate.update(pojo)
Please note i am using Springs Hibernate Template and the pojo has 1-many Parent-Child relationship .

Here is more info
Updating associated objects results in "deletion of all records from intermediate/association table & then insertion of updated records".
For example
The associated objects in my case are DeviceType and DeviceTypeRoles. Here is the sequence of method calls to update associated objects
In JSF Backing Bean

public void updateDeviceType(){
deviceType.setId(Long.valueOf(selectedDeviceType));
deviceType.setDeviceTypeRoles(createDeviceTypeRoleSet());
deviceTypeManager.updateDeviceType(deviceType);
this.deleteBtnMode = true;
FacesUtils.addInfoMessage("update", "DeviceType", deviceType.getName());
}


In Spring Bean


public void updateDeviceType(DeviceType deviceType){
logger.info(" *** In updateDeviceType Manager method *** ");
System.out.println(" *** In updateDeviceType Manager method *** ");
deviceType.setNamsUser(baseManager.getNamsUserByChangeUserId());
deviceType.setChangeDate(new Date());
deviceTypeDao.update(deviceType);
}

In HibernateImpl

public void update( DeviceType object) {
hibernateTemplate.update(object);
}


Hibernate Mapping File

<set name="deviceTypeRoles" inverse="true" cascade="all,delete-orphan">
<cache usage="read-write" />
<key>
<column name="DEV_TYPE_ID" precision="10" scale="0" not-null="true" />
</key>
<one-to-many class="com.boeing.nmt.nams.model.DeviceTypeRole" />
</set>

Any pointers/suggestions will be highly appreciated


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 7:13 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
What is the primary key on deviceTypeRole class. Is it being modified anywhere ?

What about the set, is it being reset after being loaded?

Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 11:50 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Here is my test case with the log:
Code:
<class name="Self">
      <id name="id" column="id" type="long" unsaved-value="0">
          <generator class="increment"/>
      </id>
      
      <property name="name"/>
      
      <set name="children"  cascade="all-delete-orphan">
         <key column="parent_id"/>
         <one-to-many class="Self" />
      </set>
      
      <many-to-one name="parent" column="parent_id" class="Self"/>
      
   </class>


Test method:
Code:

      Self a = new Self();
      a.setName("parent");
      Session s = factory.openSession();
      s.save(a);
      
      s.flush();
      
      a = (Self)s.load(Self.class, a.getId());
      
      Self b = new Self();
      b.setName("child1");
      
      a.getChildren().add(b);
      
      b = new Self();
      b.setName("child2");
      
      a.getChildren().add(b);
      
      s.update(a);
      
      s.flush();
      
      a = (Self)s.load(Self.class, a.getId());
      
      a.getChildren().remove(b);
      
      s.update(a);
      
      s.flush();
      
      s.close();
      
   


And here goes the log:

Code:
INFO: schema export complete
Hibernate: select max(id) from Self
Hibernate: insert into Self (name, parent_id, id) values (?, ?, ?)
Hibernate: insert into Self (name, parent_id, id) values (?, ?, ?)
Hibernate: insert into Self (name, parent_id, id) values (?, ?, ?)
Hibernate: update Self set parent_id=? where id=?
Hibernate: update Self set parent_id=? where id=?
Hibernate: update Self set parent_id=null where parent_id=? and id=?
Hibernate: delete from Self where id=?
Jun 27, 2007 9:18:02 PM org.hibernate.impl.SessionFactoryImpl close


Let me know if you are trying something different than above.

Regards,
Jitendra
*Please do rate if it helps*


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 2:03 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Hi Jitendara
I highly appreciate your time for helping.

Quote:
What is the primary key on deviceTypeRole class. Is it being modified anywhere ?


The primary key on deviceTypeRole class is ID. It also has device_type_Id and Role_Id. Here is the structure

Code:
SQL> desc device_type_role
Name                                      Null?    Type
----------------------------------------- -------- -----------
ID                                        NOT NULL NUMBER(10)
DEV_TYPE_ID                               NOT NULL NUMBER(10)
ROLE_ID                                   NOT NULL NUMBER(10)
CHANGE_USER                               NOT NULL NUMBER(10)
CHANGE_DATE                               NOT NULL DATE



The primary key on deviceTypeRole class (i.e. ID) isn't modified anywhere as explained below

Step 1
We have dropdown to perform CRUD. The dropdrown has DeviceTypeID values. Whenever user picks a value from dropdown (i.e. onChange event) I am loading DeviceType object (i.e. Parent class), which has set of associated objects i.e. DeviceTypeRoles
Code:
deviceType=deviceTypeManager.getDeviceType(selectedDeviceType);
this.deviceTypeRoles = new ArrayList (deviceType.getDeviceTypeRoles());


Step 2

From deviceTypeRoles object , i extract the roleId and roleName and add it ArrayList so as to render it on the User Interface.

private List deviceRoles = = new ArrayList();
this.deviceRoles.add(new SelectItem(roleId.toString(),role.getName()));

Please note the ArrayList deviceRoles has value binding with user inetrface and will have latest set of roles added/removed by the user on user interface

As the ArrayList deviceRoles has latest set of roles, i pass that as argument to my update method in the JSF Backing Bean

Step 3

deviceTypeManager.updateDeviceType(deviceType, getDeviceTypeRolesSet());

public Set getDeviceTypeRolesSet()
{

Set deviceTypeRoleSet = new HashSet();
deviceTypeRole = new DeviceTypeRole(); //creating new instance of pojo i.e. association class

for (Iterator iter = deviceRoles.iterator(); iter.hasNext();) {
SelectItem selectItem = (SelectItem) iter.next();
String roleId = (String)selectItem.getValue();
deviceTypeRole = deviceTypeManager.getDeviceTypeRoleByRoleId(Long.valueOf(roleId));// For each role on the user interface load the DeviceTypeRole object

deviceTypeRole.setDeviceType(deviceType);
deviceTypeRoleSet.add(deviceTypeRole);
}

return deviceTypeRoleSet;
}


Quote:
What about the set, is it being reset after being loaded?

As shown in Step3 the set is being reset with the latest set of roles added/removed from the user interface

Step 4
In the business layer i.e. Spring , here is the snippet for update

Code:
public void updateDeviceType(DeviceType deviceType, Set<DeviceTypeRole> deviceTypeRoles) {
         System.out.println("In updateDeviceType Manager method");         
         deviceType.addAll(deviceTypeRoles);
         this.deviceTypeDao.update(deviceType);
      }


Step 5
In the DeviceType POJO , here is the snippet for addAll called from update method of business layer
Code:
public void addAll (Set aDeviceTypeRoles) {
this.getDeviceTypeRoles().clear();
for (Object o: aDeviceTypeRoles) {
          DeviceTypeRole dtRole = (DeviceTypeRole) o;
          System.out.println("Name="+dtRole.getNamsRole().getName());
          add(dtRole);
          
       }

public void add (DeviceTypeRole dtr) {
       
       this.deviceTypeRoles.add(dtr);       
       dtr.setDeviceType(this);
       
       
    }


Thanks again for helping


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 2:50 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
The problem is in Step5 addAll method.
Code:
this.getDeviceTypeRoles().clear();

This tells the hibernate to delete whatever was there. I think the new objects being added do not have the id of the old ones. Since your primary key is ID, hibernate will check if the object with the id in the db is present in the selection, if not then it will delete the row with that id. Then since the ids in the newly added objects to the collection is 0, hibernate thinks these are newly added objects.

You need to have some kind of equals method in ur object and then compare if they are new then add to the list, if they are old do nothing, if there are any in the collection not present in the list then drop them.

This should take care of your problem of deleting and re-adding :-).

cheers!
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 27, 2007 4:23 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Perfect answer. You deserve total credit :)-
You are absolutely correct in saying
Quote:
The problem is in Step5 addAll method.

this.getDeviceTypeRoles().clear();



Like you i too guessed it correctly & spend whole day on fixing just that line of code as follows but with no success
Code:
getDeviceTypeRoles().addAll(aDeviceTypeRoles); // Is like Union add new roles to exsisting role set
getDeviceTypeRoles().retainAll(aDeviceTypeRoles); // Is like Intersection, retain only those roles in the exsisting role set which are present in new set


Please note i replaced my entire code in addAll() method with the above two lines. I was hoping Hibernate to do update this time as it holds onto the IDs of exsisting DeviceTypeRole objects and ofcourse for newly added objects it will do insert.

Thanks for pointing out Best Practices i.e. implementation of "equals()" method. Wondering if this implementation can be done in business Layer i.e. Spring instead of Pojos in Hibernate.
We are using ormtool to generate Hibernate Pojos & reluctant to modify it

I will highly appreciate if you could paste a snippet of equals() method implementation

Thanks for helping


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 28, 2007 10:52 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
equals method is very subjective matter. Simplest would be to compare the primary keys of the two objects, the ids in your case.

I do no have much idea about springs, this can probably be answered easily in a spring forum.

PS.*I can't see any of my posts being credited*.

Regards,
Jitendra

*Please do rate if it helps*


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 28, 2007 3:26 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Thanks Jitendara
Yesterday i tried crediting your posts, not sure how to do this. I mean i didnt see any links for crediting your post.
In the meantime i would highly appreciate if you could show a snippet code on how to implement "equals" and "hashcode" method in Hibernate. I will get an idea to have similar implementation in business Layer.
Its years that i have looked into Core Java so appreciate your patience

Thanks for helping


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 2:17 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Please do figure out how to credit. It takes a lot of effort to help.

This is what I have:
Code:
/* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object pObj) {
        if(! (pObj instanceof DictionaryEntryEntity)) return false; 
       DictionaryEntryEntity entryEntity = (DictionaryEntryEntity) pObj;
       if(entryEntity != null && entryEntity.getId() == this.getId()) {
          return true;
       }
       return false;
    }
   
    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
       return super.hashCode();
    }


Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 4:27 pm 
Beginner
Beginner

Joined: Tue May 08, 2007 1:20 pm
Posts: 24
Thanks Jitendara . I finally rated your posting. All this time i was looking at the posting without logging in i.e. just searching hence it didnt show up the link for rating

Good to have people like you in Hibernate Forums who help others. I hope you are somewhere around me so that i can learn more from you. As i am learning Hibernate i frequently see LazyIntialization Exception in my code. I read the Hibernate docs which says by default Hibernate uses Lazy fetching strategy and hence suggest to access the collection before closing of session i.e. account.getPermissions() in Hibernate docs

But in real time we have business Layer objects accessing hibernate objects thru named queries etc . Is their is a way i can fine-tune my application to avoid Lazy Initialization Exception. We have discarded the option of using OpenSessionInViewFilter. Any suggestions/pointers will be appreciated


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.