-->
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.  [ 4 posts ] 
Author Message
 Post subject: One shot delete
PostPosted: Wed Dec 01, 2010 10:08 am 
Newbie

Joined: Sat Feb 23, 2008 4:09 pm
Posts: 3
This question has been asked many times, but I did not find a clear solution, so I'm asking this again here in the hope someone can help.
The scenario is like this: I have a 'person' which can have zero, one or more 'products'.
So I made a one-to-many set association from Person to Product. The association is uni-directional, from Person to Product.

What I want is that when I delete a Person, the products are deleted as well.
I, however, want hibernate to do this in one single query, like: 'delete from product where person_id = <id>'

But whatever I try, hibernate just keeps on deleting the products one by one:

Code:
31398 [main] DEBUG org.hibernate.SQL  - delete from product where id=?
31399 [main] DEBUG org.hibernate.SQL  - delete from product where id=?
31400 [main] DEBUG org.hibernate.SQL  - delete from person where id=?


In this case a delete statement per product entry would yield in serious performance degradation
(This is only a proof of concept for a table who can contain thousands of childs records.)

I also tried deleting the product the products with HQL.
This works, however, the products also have a <map> assocation, and the cascade settings are discarded when using HQL. So for this HQL is not a solution either.
The only solution I see right now is using plain SQL....

Code:
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.query.substitutions">true 1,false 0</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.jdbc.fetch_size">100</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>


Code:
<hibernate-mapping default-access="field" >
   <class name="entities.Person" table="person">
      <id name="id" column="id" access="property">
         <generator class="native"/>
      </id>

      <set name="products" cascade="all-delete-orphan">
         <key column="person_id" not-null="true" update="false" />
         <one-to-many class="entities.Product"/>
      </set>
   </class>
</hibernate-mapping>


Code:
<hibernate-mapping default-access="field" >
   <class name="entities.Product" table="product">
   
      <id name="id" column="id" access="property">
         <generator class="native"/>
      </id>
      
      <property name="name" column="name"/>
   </class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: One shot delete
PostPosted: Wed Dec 01, 2010 12:00 pm 
Senior
Senior

Joined: Fri May 08, 2009 12:27 pm
Posts: 168
I'm not sure that Hibernate's semantics allows it to do a single-query DELETE. It may be violated in cases where a separate Session inserts Product records while your session is deleting the Person.
Of course, you want that other Session to fail, but Hibernate seems not to know this - possibly because the appropriate option on the association is missing. Something that tells Hibernate that a Product always requires a Person to exist, maybe.

The other approach would be to let the database handle this.
Define a foreign key with a CASCADE DELETE constraint; when you delete() the Person, the Product records in the database will automatically and efficiently go away, too. (You need to take care that Hibernate is aware of that: any affected Product records need to be in a detached state after Person deletion. Hibernate would need to know that it can rely on a CASCADE DELETE in the database, else it will still want to delete the Product records in the database, so I guess there's a separate option on the Hibernate association required for that.)
I'm a bit on shaky ground here, I don't know whether Hibernate is smart enough and knows what it can delegate to the database's CASCADE DELETE option and what it needs to do explicitly. Maybe it can't do that (yet).

Note that Hibernate isn't really built for bulk operation anyway. For example, it tends to get noticeably slower when it has tens of thousands of entities in its session cache, and can slow to a crawl if you insist on loading millions of entities.
The lesson is that you should limit to a few hundred entities at a time, and at that volume of data, the difference between a single DELETE or multiple DELETEs isn't that important anymore. Well, for latency anyway - throughput can still be affected, but then throughput impact depends on how many deletions you have per hour. If that number is as low as is typical, you won't have to worry about throughput either.


Top
 Profile  
 
 Post subject: Re: One shot delete
PostPosted: Thu Dec 30, 2010 7:46 am 
Newbie

Joined: Thu Dec 30, 2010 7:39 am
Posts: 1
You need to understand the topic of who controls the FK (foreign key) population, Parent of Child.

In case of inverse=true or JPA's mappedBy, the control is moved to the Child, so child is responsible to populate the correct FK value.

However, once you have inversed the control to the child, you cant call anymore Parent.childs.clear (psuedo code) and expect Parent to delete the children. Doing so will throw an exception about FK violation.

In order to achieve what you need, just avoid the inversion of control. This would force the Parent to control its children, and calling Parent.childs.clear will be done by single delete.

If you need more in depth understanding, post here and i will elaborate ...


Top
 Profile  
 
 Post subject: Re: One shot delete
PostPosted: Mon Jan 03, 2011 10:56 am 
Senior
Senior

Joined: Fri May 08, 2009 12:27 pm
Posts: 168
Ah, that's a detail that I wasn't aware of, chulli; thanks for the tip.
I'll look into it and come back if/when I need more info. (I rarely delete records anyway, so...)


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