-->
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.  [ 3 posts ] 
Author Message
 Post subject: on-delete="cascade" not working for scalar collect
PostPosted: Wed Aug 30, 2006 3:44 pm 
Newbie

Joined: Wed Aug 30, 2006 3:17 pm
Posts: 11
I have an entity class that contains (among other things) a Map of strings to strings, backed up by an Oracle database. My mapping for it looks something like this (paraphrased to eliminate application-specific information):



Code:
<class name="SomeEntity" table="SomeEntities">

   <id name="id" column="entity_id" type="java.lang.Long">
      <generator class="native" />
   </id>

   <map name="attributes" table="Attributes" lazy="false" cascade="all-delete-orphan" sort="unsorted">
      <key column="entity_id" not-null="true" on-delete="cascade" />
      <map-key column="attrib_name" type="string" />
      <element column="attrib_value" type="string" unique="false" not-null="false" />
   </map>

</class>


The schema generator tool puts the ON DELETE CASCADE attribute on the foreign key constraint, which is what I want.

However, when I actually try to run the code, Hibernate complains that "only inverse one-to-many associations may use on-delete='cascade'". There is no way to turn this into a one-to-many association without creating an entirely new class to represent a single name-value pairing, which defeats the whole purpose of having Maps to begin with!

I've tried just adding an inverse="true" attribute to the <map>, but that just makes it so that ON DELETE CASCADE is not included in the schema, while Hibernate still seems to be relying on the ON DELETE CASCADE behavior, because when I try to delete a SomeEntity object (actually, I'm deleting a parent of SomeEntity that has properly-functioning ON DELETE CASCADE behavior), the foreign key constraint fails (suggesting that Hibernate is now ignoring the cascade="all-delete-orphan" attribute).

Am I doing something wrong, or does Hibernate really not support ON DELETE CASCADE for collections of primitive objects (which seems to me to be the case when you'd most want to use it!)?


I'm using Hibernate v3.1.1 (though I doubt that matters, since I didn't see anything about this in the latest changelogs).

_________________
Rich Eggert


Top
 Profile  
 
 Post subject: On Delete Cascade constraints with indexed list elements?
PostPosted: Tue Sep 12, 2006 9:19 am 
Newbie

Joined: Tue Sep 12, 2006 7:03 am
Posts: 7
Location: Berlin
I tried this with one-to-many associations, it may still provide a hint for the map problem:

Suppose a class Shelf that contains a set of Books.

Code:
<class name="Shelf" table="SHELF">
      <id name="shelfID" type="int" column="SHELF_ID">
         <meta attribute="scope-set">protected</meta>
         <generator class="my.IDGenerator"/>
      </id>

      <!-- Cascaded delete is performed by foreign key integrity constraint
         and must be declared for the key column-->
      <set name="books"
         cascade="save-update"
         inverse="true"
      >
         <key column="SHELF_ID" on-delete="cascade"/>
         <one-to-many class="Book"/>
      </set>
</class>


If there is a foreign key constraint on the BOOK table

ALTER TABLE BOOK ADD CONSTRAINT FK_BOOK_SHELF FOREIGN KEY (SHELF_ID) REFERENCES SHELF(SHELF_ID) ON DELETE CASCADE;

the database takes care of deleting the books if the referenced shelf is taken out. As I understand it, you tell Hibernate with cascade="save-update" and on-delete="cascade" that it does not need to delete books prior to removing a shelf.

However, I stepped on a similar problem as you when I try to change the set into an ordered list (as my books are usually not placed onto the shelf in an orderly manner, sorting by author or title does not preserve my disorder ;-) ):

Code:
<class name="Shelf" table="SHELF">
      <id name="shelfID" type="int" column="SHELF_ID">
         <meta attribute="scope-set">protected</meta>
         <generator class="my.IDGenerator"/>
      </id>

       <!-- inverse must be false for indexed collections -->
      <list name="books" cascade="all" inverse="false">
         <key column="SHELF_ID"/>
         <list-index column="BOOK_ORDER"/>
         <one-to-many class="Book"/>
      </list>
</class>


Inverse needs be true for on-delete="cascade", which is not possible for indexed lists. In the above example above, Hibernate deletes all books when deleting a shelf because of cascade="all". This only works when there is no "ON DELETE CASCADE" foreign key constraint on BOOK.

So the answer for you may be: just leave out the on-delete="cascade" and Hibernate will not generate a foreign key database constraint but still delete the map entries, given appropriate cascade="..." settings.

My Question: is there a way in Hibernate to use indexed lists with an "ON DELETE CASCADE" (on-delete="cascade") foreign key constraint?


Fritz

_________________
His Darkness and His Brightness
exchanged greetings of extreme politeness


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 12, 2006 11:46 am 
Newbie

Joined: Wed Aug 30, 2006 3:17 pm
Posts: 11
I ended up giving up and removing all my uses of on-delete and just using cascade="all,delete-orphan". Not only does on-delete seem to not be supported for indexed collections (such as maps and ordered lists), but cascade= is completely ignored for HDL queries (though on-delete still works), resulting in unexpected behavior in my case, where I had a one-to-many relationship where the "many" side itself contained a map, and I was trying to do an HDL "DELETE" query on the "one" side, expecting the deletion to cascade all the way down. on-delete caused it to cascade to the "many" side, but it did not cascade to the map elements (because on-delete must be specified on an "inverse" relationship), causing all the map elements to be orphaned from their container. I removed the on-delete and tried to get Hibernate to cascade the deletions itself, but it cascaded none of them. Finally, I had to resort to doing a selection query against the parent entity and iterate through the result set, calling delete on each element individually so that Hibernate would cascade the operation all the way down through the child entity to the map elements.

It would seem that Hibernate just converts the HDL queries directly into SQL without considering any special behaviors (such as "cascade") that might apply to the targets of the query. This was presumably done for performance reasons so that Hibernate would not need to identify all the rows affected by a query so that it could cascade any updates/deletions to the children of those rows (which could become very time-consuming).

_________________
Rich Eggert


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