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: Why is hibernate updating a row before deleting it?
PostPosted: Tue Apr 14, 2009 9:07 am 
Senior
Senior

Joined: Tue May 10, 2005 9:00 am
Posts: 125
Hibernate version:
3.2.6.ga
Mapping documents:

Code:
<class name="company.WorkflowWatch" table="INTRANET_WF_WATCH">
  <cache usage="read-write"/>
  <id name="id">
    <column name="watch_id" not-null="true" unique="true" />
    <generator class="sequence">
      <param name="sequence">RH_GENERIC_SEQ</param>
    </generator>
  </id>
  <!-- .... other simple properties ...-->
  <many-to-one name="profile" column="PROFILE_ID" not-null="false" cascade="save-update"/>

</class>
Code:
<class name="company.Profile" table="INTRANET_PROFILE" lazy="false">
  <cache usage="read-write"/>
  <id name="id">
   <column name="profile_id" not-null="true" unique="true" />
      <generator class="sequence">
       <param name="sequence">RH_GENERIC_SEQ</param>
      </generator>
  </id>
  <!-- .... other properties ...-->
   <set name="watchedWorkflows"  cascade="all,delete-orphan">
       <key column="PROFILE_ID"/>
       <one-to-many class="be.rmi.intranet.profile.WorkflowWatch"/>
   </set>
</class>

Code between sessionFactory.openSession() and session.close():
Code:
      s.flush();
      id = w.getId();
      Long id2 = p2.getId();
      System.out.println("removing");
      p2.getWatchedWorkflows().remove(w);
      s.save(p2);
      System.out.println("flushing");
      s.flush();
      s.close();
      s = WorkflowsService.getInstance().createSession();
      assertNull("an update of profile should have remove watch",s.get(WorkflowWatch.class, id));


The generated SQL (show_sql=true):
Code:
removing
flushing
Hibernate: update INTRANET_WF_WATCH set PROFILE_ID=null where PROFILE_ID=?
Hibernate: delete from INTRANET_WF_WATCH where watch_id=?




With above mapping, when i remove an item from a set, hibernate is supposed to delete corresponding row for item (delete-orphan rule). However, why does it systematically issue an update on the very same row before deleting it? It first set the foreign key of PROFILE_ID to null before deleting. Not only does it waste time, it also means that i have to remove my "not null" constraint from this foreign key in the database or hibernate issue an exception abuot not null when asked to delete an item.... Is there any way to ask hbernate not to do that non-sense update?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 14, 2009 9:43 am 
Regular
Regular

Joined: Thu Sep 06, 2007 2:22 am
Posts: 108
Location: Noida,India
added inverse attribute in the set element-

Code:
<set name="watchedWorkflows"  cascade="all,delete-orphan" inverse="true">



Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 15, 2009 4:22 am 
Senior
Senior

Joined: Tue May 10, 2005 9:00 am
Posts: 125
i never thought this would be related. Does that mean that the set does not manage anymore the relation? If yes, that mean i am not allowed to do this anymore:

Code:
      p1.getWatchedWorkflows().add(new WatchedWorkflow());
      s.saveOrUpdate(p1);
      s.flush();

because the profileID of workflowwatch table would not be initialized.

This is not a problem in this specific case (we are managing at bean level a 2 ways relationship, with a protected field and a bit of code, we can have the add() issue a w.setProfile()), but it becomes a problem if i have moev to a one way relationship profile
Code:
(1)------->(0..n) workflowWatch


Not all our relationships are two way, and we would like hibernate to delete orphans without first updating them (which is a non-sense), without using inverse because the collection is the "owner" of the foreign key.

thnaks for your help (and patience)

edit: using an unidirectional one-to-many relationship with a join table seems to do the trick too.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 15, 2009 5:37 am 
Regular
Regular

Joined: Thu Sep 06, 2007 2:22 am
Posts: 108
Location: Noida,India
did it help you? If yes, please don't forget to rate the post.

if you still want to use same code

Code:
p1.getWatchedWorkflows().add(new WatchedWorkflow());

to saving the WatchedWorkflow, this can be done easily.

Add a new method to set the new instance of WatchedWorkflow in Profile class like this

Code:
public void addWatchedWorkFlows(WatchedWorkflow w){
//set bidirectional relationship here.
w.setProfile(this);
watchedWorkflows.add(w);
}



Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 15, 2009 7:14 am 
Senior
Senior

Joined: Tue May 10, 2005 9:00 am
Posts: 125
ok, found out how to get an unidirectional one-to-many with hibernate auto updating the collection content without the need for inverse. Inverse is good for bidirectionnal associations, for unidirectional, the trick is to use "unidirectional one-to-many with join table", (examples are in hibernate doc). As is, have all informations needed for all my collection use cases :)

thanks all


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.