代码之家  ›  专栏  ›  技术社区  ›  Nemi

休眠-如何在分离的对象上级联删除

  •  2
  • Nemi  · 技术社区  · 16 年前

    我有一个Hibernate对象,它通过EJB被分离并转移到一个厚的JAVA Swing客户端。然后以某种方式修改对象并返回到服务器,然后服务器将修改后的对象更新到数据库。对于发生更改的属性,一切都正常工作,但我在如何删除 many-to-one 映射。

    例如,给定以下映射:

    <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>
        ...
    

    假设我有一个病人对象被发送给客户。用户以前添加了地址。每个患者只能有一个地址。在客户机上,如果用户删除了地址,我会调用 setAddress(null) 在返回到服务器之前在患者对象上。当我到达服务器时,它将地址字段保存为空,但将地址记录保留在数据库中。我明白为什么要这样做。我只破坏了这段关系的一端。我最好用 delete-orphan . 但是,根据Hibernate文档, 删除孤儿 不适用于 多对一 映射。正确的过程是调用服务器(伪代码):

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

    这个模式的问题是,如果我想坚持简单地传递我想要保存的病人对象的过程,我就无法知道它是否有一个需要删除的地址。为了解决这个问题,我必须做一些不那么优雅的解决方法,例如查询数据库以查看是否有地址,如果传递的对象中的地址为空,则将其删除,或者创建 setDeleteAddress(boolean) , getDeleteAddress() 方法,如果用户希望删除地址,则在客户端设置这些方法。

    另一种选择是使患者和地址之间的关联成为一对多。那我可以用 删除孤儿 . 但是,由于这真的是一对一的关系,我需要像这样在病人类中放置一些疯狂的getter/setter,这样在没有集合的情况下,我就不会在代码中乱丢集合引用:

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

    有没有更好的方法来解决这个问题?如何处理删除已分离对象上的实体?

    3 回复  |  直到 16 年前
        1
  •  0
  •   ChssPly76    16 年前

    将地址映射为 many-to-one 似乎是你问题的根源。地址是这种关系中的“父母”,这没有什么意义。考虑将其映射为组件或一对一。任何一种方式都不应涉及收集。

        2
  •  0
  •   waxwing    16 年前

    我似乎记得,在某些情况下,将一个映射到与单个属性的关系实际上是可能的。我无法验证这一点,但在 documentation .

    或者,具有唯一约束的外键(从员工到人员)可以表示为:

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

    通过将以下内容添加到人员映射中,可以使此关联双向进行:

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

    你可能需要做点小调整,然后再加上 cascade="delete" 到一对一映射。我自己从来没有试过。如果您可以控制数据库模式,最好的选择是CHSSPLY76的答案。

        3
  •  0
  •   Nemi    15 年前

    我最终只是创造了一个 deleteFlag Address 类以向EJB指定 地址 有问题的应该从 Patient .