-->
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: Order of cascaded deletes
PostPosted: Fri Apr 01, 2005 2:24 pm 
Beginner
Beginner

Joined: Sun Feb 20, 2005 12:14 am
Posts: 49
We have a Customer, Order and CreditCard. The mapping for these entities are below.

1. A CreditCard is always associated with a Customer.
2. An Order is always associated with a Customer.

The problem:
When we delete a Customer this cascades the delete to CreditCards and Orders the way we want to , but Orders should be deleted first and then CreditCards. This is because Orders need to have CreditCards.

Is there a way in Hibernate to control the order of cascading deletes? Or is there an alternative that we can use to achieve the same effect?

Thanks.

Hibernate version: 3.0

Mapping documents:
Code:
   <class name="Order" table="`order`">
      <id name="id" unsaved-value="0">
         <generator class="native"/>
      </id>
      
      <version name="version" type="long" unsaved-value="null"/>

      <many-to-one name="creditCard" column="creditCardId" lazy="true" class="CreditCard" not-null="true"/>
      <many-to-one name="customer" column="customerId" lazy="true" class="Customer" not-null="true"/>

        <set name="orderItems" access="field" lazy="true" cascade="all">
           <key column="orderId" not-null="true"/>
           <one-to-many class="OrderItem"/>
        </set>
       
        <set name="destinations" access="field" lazy="true" cascade="all">
           <key column="orderId" not-null="true"/>
           <one-to-many class="Destination"/>
        </set>
       
   </class>


Code:
    <class name="Customer" table="customer">
        <id name="id" unsaved-value="0">
           <generator class="native"/>
        </id>

       <version name="version" type="long" unsaved-value="null"/>
       
        <property name="emailAddress" type="string" unique="true"/>
        <property name="password" type="string"/>
      <component name="nameComponent">
         <property name="first" type="string"/>
         <property name="last" type="string"/>
         <property name="company" type="string"/>
      </component>
      
      <one-to-one name="cart" class="Cart" cascade="all" lazy="true"/>
            
        <set name="contacts" access="field" lazy="true" cascade="all">
              <key column="entityId" foreign-key="none"/>
            <one-to-many class="Contact"/>
        </set>

        <set name="orders" lazy="true" cascade="all" >
           <key column="customerId"/>
           <one-to-many class="Order"/>
        </set>

        <set name="creditCards" lazy="true" cascade="all-delete-orphan">
           <key column="customerId"/>
           <one-to-many class="CreditCard"/>
        </set>
   </class>

Code:
   <class name="CreditCard" table="creditcard">
      <id name="id" unsaved-value="0">
         <generator class="native"/>
      </id>
      
      <version name="version" type="long" unsaved-value="null"/>

      <component name="addressComponent">
         <property name="street1" type="string" not-null="true"/>
         <property name="street2" type="string"/>
         <property name="city" type="string" not-null="true"/>
         <property name="state" type="string" not-null="true"/>
         <property name="zip" type="string" not-null="true"/>
      </component>
      
      <property name="cardType" type="string" not-null="true"/>
      <property name="cardNumber" type="string" not-null="true" unique="true"/>
      <property name="expiry" type="calendar" not-null="true"/>
      <property name="securityCode" type="string"/>
      <property name="nameOnCard" type="string" not-null="true"/>
      
      <many-to-one name="customer" column="customerId" lazy="true" class="Customer"/>
   </class>


Full stack trace of any exception that occurs:
Code:
DEBUG - could not delete: [com.allegrocentral.tandoori.beans.CreditCard#1] [delete from creditcard where id=? and version=?]
java.sql.SQLException: Cannot delete or update a parent row: a foreign key constraint fails
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2847)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1531)
   at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1347)
   at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:958)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1957)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1880)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1741)
   at com.mchange.v2.sql.filter.FilterPreparedStatement.executeUpdate(FilterPreparedStatement.java:71)
   at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2085)
   at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2227)
   at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:59)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:675)
   at com.allegrocentral.tandoori.persistence.utils.DBManager.commitTransaction(DBManager.java:55)
   at com.allegrocentral.tandoori.persistence.daos.TestDestination.testInsertDeleteDestination(TestDestination.java:127)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at junit.framework.TestCase.runTest(TestCase.java:154)
   at junit.framework.TestCase.runBare(TestCase.java:127)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:118)
   at junit.framework.TestSuite.runTest(TestSuite.java:208)
   at junit.framework.TestSuite.run(TestSuite.java:203)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)

Name and version of the database you are using: MySQL 4.1.10-nt


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 04, 2005 2:32 am 
Beginner
Beginner

Joined: Sun Feb 20, 2005 12:14 am
Posts: 49
I have yet to find a solution to the problem I posted in my original post above.

A Customer has a CreditCard. A CreditCard cannot exist in the system without being associated with a Customer.

An Order cannot exist without being associated with a Customer and an Order cannot exist without being associated with a CreditCard.

When I delete a Customer, I want the delete to cascade to the Customer's Orders and CreditCards. The problem though is that I want the delete to first cascade to the Orders and then the CreditCards. At the moment when I delete a Customer, first the CreditCards get deleted which cause a foreign key constraint violation since the Order hold that reference.

Is there a way to control the order of cascade deletes in Hibernate, or is there a different approach to solve this problem? The mapping files are posted in my original post.

At the moment I first delete the Orders of the customer explicitly and then delete the Customer (which cascades to the CreditCards). This solution works fine. I am wondering if I could achieve the same result by a single delete on a Customer?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 9:46 am 
Regular
Regular

Joined: Thu Dec 02, 2004 7:11 am
Posts: 85
<many-to-one name="creditCard" column="creditCardId" lazy="true" class="CreditCard" not-null="true" cascade="delete" />


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 11:35 am 
Beginner
Beginner

Joined: Sun Feb 20, 2005 12:14 am
Posts: 49
I think I should have been more explicit in defining the problem above. When an order gets deleted, I do not want to delete the CreditCard(s). Only when a customer gets deleted I want to delete all orders and all credit cards associated with the customer being deleted.

I have set my cfg.xml to do exactly just that, but the only problem is that when i call delete(customer) the credit cards get deleted first and then the orders. The problem with that is that when credit cards are deleted the orders still have a foreign key reference to credit cards. This why the delete fails because of a foreign key constraint violation.

Therefore i was wondering if there was a way in hibernate in order to delete the entities in the right order.


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.