views:

86

answers:

2

Hi, I'm sligthly confused as to how the cascade="delete" works. I defined the mapping in the following way in the City mapping file:

<set inverse="true" name="client" cascade="delete">
  <key>
    <column name="id_name"/>
  </key>
    <one-to-many class="model.Client"/>
 </set>

The class Client has a foreign key to a class City.

So when I run:

List object = null;
try {
   org.hibernate.Transaction tx = session.beginTransaction();
   try {
       session.delete("from City where row_id=" + row_id and table_id = " + table_id);
   } catch (Exception e) {
       e.printStackTrace();
   }
}

Should all the clients be deleted as well or do I have to handle it somehow? Am I passing the query as a method parameter correctly to the delete() method of a session? Thanks for any help. Best Regards, sass.

A: 
  1. If you delete a city, then all clients will be deleted as well. If you delete a client, the city will be left alone.

  2. session.delete() can't be called with a HQL query. You must pass it one city to delete.

Alternatively, you can use session.createSQLQuery() to create a delete statement. That allows you to delete many cities in one go. The drawback with this method is that you must delete the clients yourself and flush the cache (Hibernate makes no attempt to understand what your query might mean).

Aaron Digulla
I was reffering to the information that session.delete() “Delete all objects returned by the query. Return the number of objects deleted.” Is it not true?
sass
`Session#delete(String)` has been deprecated in Hibernate and moved to the classic API. Hibernate now offers some support for DML style operations (a la JPA).
Pascal Thivent
Thanks a lot. I must have looked at some really old information.
sass
A: 

I'm slightly confused as to how the cascade="delete" works (...)

Cascading a delete operation means that if you delete a parent, the operation will be propagated along the association. So in your case, deleting a City entity should be propagated to the Clients.

So when I run (...) Should all the clients be deleted as well

The Session#delete(String) method that takes a HQL query string, executes it, iterates over the results and calls Session#delete(Object) on each object respect cascading (so the Clients will be deleted if your query is really a HQL query).

But this method is old and has been deprecated in Hibernate 3 (and moved to the "classic" Session interface), I do not really recommend it (it performs 1+N operations and is pretty inefficient to delete a huge number of results).

If this is a concern, prefer the bulk delete support offered by Hibernate:

int deleteCount = session.createQuery("delete from Foo where bar = :bar") 
    .setParameter("bar", bar);
    .executeUpdate()

But note that bulk delete has restrictions:

  • You can not use aliases.
  • No inner joins in the query (although you can use subselects in the where clause).
  • A bulk delete does not cascade (and won't take care of join tables).

So with a bulk delete, you'd have to delete the Client before the City. But performances are much better.

PS: You need to commit() at some point (and also improve your error handling i.e. rollback() in the catch block)

References

Pascal Thivent
Thanks a lot. However, I prefer to use the cascade delete since it handles a good part of the code. The code that i presented in the original post is just a part of the code, so there is error handling and commit.
sass
@saas You're welcome.
Pascal Thivent