简体   繁体   中英

Hibernate - How to cascade delete on detached objects

I have a hibernate object that gets detached and transferred to a thick java swing client using EJBs. The object is then modified in some way and returned to the server where the server then updates the modified object to the database. Everything works well for properties that change, but I am having a problem on how to delete a many-to-one mapping.

For instance, given the following mapping:

<hibernate-mapping>
<class name="com.wg.common.bean.Patient" table="patient">
    <id name="id" type="integer">
        <column name="id" />
        <generator class="sequence">
            <param name="sequence">patient_id_seq</param>
        </generator>
    </id>
    <many-to-one name="address" class="com.wg.common.bean.Address" cascade="all">
        <column name="address_id" />
    </many-to-one>
    ...

Say I have a patient object that is sent to the client. The user has previously added an address. There can only be one address per patient. On the client if the user removes the address, I call setAddress(null) on the patient object before returning to the server. When I get to the server it saves the address_id field as null, but leaves the address record in the database. I understand why it is doing that. I am only breaking one end of the relationship. Preferably I would use delete-orphan . However, according to the Hibernate documentation, delete-orphan is not available for many-to-one mappings. The proper procedure is to call on the server (pseudocode):

Address address = patient.getAddress();
session.delete(address);
patient.setAddress(null);

The problem with this pattern is that if I want to stick to a process of simply passing back the Patient object I want saved, I have no way of knowing if it had an address that needs to be deleted. I have to do some less-than-elegant workarounds to solve this problem, such as querying the database to see if there was an Address and removing it if it is null in the passed object, or creating setDeleteAddress(boolean) , getDeleteAddress() methods in Patient class and setting those on the client side if the user wants to remove the address.

Another alternative would be to make the association a one-to-many between Patient and Address. Then I could use delete-orphan . However, since it is really a one-to-one relationship, I would need to put some crazy getter/setter in the Patient class like this so I don't litter my code with collection references when there isn't really a collection:

public Address getAddress() {
    if(addresses != null && addresses.size() > 0) return addresses.get(0);
    else return null;
}

Is there a better way to address this issue? How have you handled removing an entity on detached objects?

Mappings address as many-to-one seems to be the root of your problems. Address is the "parent" in such a relationship, which doesn't make a lot of sense. Consider either mapping it as component or one-to-one instead. No collection should be involved either way.

I seem to recall that it is in fact possible to map a one-to-relationship with a single property in some cases. I cannot verify this, but there are some hints in the documentation .

Alternatively, a foreign key with a unique constraint, from Employee to Person, can be expressed as:

<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>

This association can be made bidirectional by adding the following to the Person mapping:

<one-to-one name="employee" class="Employee" property-ref="person"/>

You may have to fiddle around a little and add cascade="delete" to the one-to-one mapping. I have never tried this myself. The best alternative is ChssPly76's answer, if you have control over the database schema.

最后,我仅在Address类中创建了deleteFlag ,以向EJB指定应从Patient删除有问题的Address

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM