Alex Rivera | Logout

Can Hibernate delete orphaned collections when updating a detached object?

Asked 2010-10-21T13:57:18.740
17

I know that deleting orphaned child objects is a common question on SO and a common problem for people new to Hibernate, and that the fairly standard answer is to ensure that you have some variation of cascade=all,delete-orphan or cascade=all-delete-orphan on the child collection.

I'd like to be able to have Hibernate detect that child collection has been emptied/removed from the parent object, and have the rows in the child table deleted from the database when the parent object is updated. For example:

Parent parent = session.get(...);
parent.getChildren().clear();
session.update(parent);

My current mapping for the Parent class looks like:

<bag name="children" cascade="all-delete-orphan">
    <key column="parent_id" foreign-key="fk_parent_id"/>
    <one-to-many class="Child"/>
</bag>

This works fine for me when updating an attached object, but I have a use case in which we'd like to be able to take a detached object (which has been sent to our API method by a remote client over HTTP/JSON), and pass it directly to the Hibernate Session - to allow clients to be able to manipulate the parent object in whichever way they like and have the changes persisted.

When calling session.update(parent) on my detached object, the rows in the child table are orphaned (the FK column is set to null) but not deleted. Note that when I'm calling session.update(), this is the first time the Hibernate Session is seeing this object instance - I am not re-attaching or merging the object with the Session in any other way. I'm relying on the client to pass objects whose identifiers correspond to actual objects in the database. For example, the logic in my API service method is something like this:

String jsonString = request.getParameter(...);
Parent parent = deserialize(jsonString);
session.update(pare
Edit
Report

1 Answer

8

Your mapping (simplified)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="br.com._3988215.model.domain">
    <class name="Parent" table="PARENT">
        <id name="id">
            <generator class="native"/>
        </id>
        <bag cascade="all,delete-orphan" name="childList">
            <key column="PARENT_ID" not-null="false"/>
            <one-to-many class="Child"/>
        </bag>
    </class>
    <class name="Child" table="CHILD">
        <id name="id" column="CHILD_ID">
            <generator class="native"/>
        </id>
    </class>
</hibernate-mapping>

produces

PARENT
    ID

CHILD
    CHILD_ID
    PARENT_ID

According what you said

I would like to be able to have Hibernate detect that child collection has been removed from the parent object, and have the rows in the child table deleted from the database when the parent object is updated

Something like

Parent parent = session.get(...);
parent.getChildren().clear();

session.update(parent);

You said it works fine because you have an attached Parent instance

Now let's see the following one (Notice Assert.assertNull(second))

public class WhatYouWantTest {

    private static SessionFactory sessionFactory;

    private Serializable parentId;

    private Serializable firstId;
    private Serializable secondId;

    @BeforeClass
    public static void setUpClass() {
        Configuration c = new Configuration();
        c.addResource("mapping.hbm.3988215.xml");

        se
answered 2010-10-30T19:54:57.200

Your Answer