【问题标题】:Before deleting an entity, deleting its parent reference(s), if any在删除实体之前,删除其父引用(如果有)
【发布时间】:2015-09-25 19:11:39
【问题描述】:

在删除实体之前,必须从其父列表中删除实体,并从实体本身中删除父实体。

示例(EJB 中的 CMT)从州到市的一对多:

public boolean delete(City city) { // Detached instance.
    City managedCity = entityManager.contains(city) ? city : entityManager.merge(city);
    managedCity.getState().getCityList().remove(managedCity);
    managedCity.setState(null);
    entityManager.remove(managedCity);
    return true;
}

语句managedCity.setState(null); 将实体的父级设置为null。由于它是一个托管实体,因此对该实体所做的任何更改都会影响到底层数据库。相应地,将生成一个UPDATE 语句,并将数据库表中的state_id 设置为null

UPDATE db.city SET state_id = ?, row_version = ? WHERE ((city_id = ?) AND (row_version = ?))
bind => [null, 2, 10, 1]

这是非常不受欢迎的。除了发出附加的UPDATE 语句外,它还尝试将数据库表中的state_id 设置为null,如果对数据库表中的相应列强制执行NOT NULL 数据库约束,则会导致问题。

如何在删除实体本身之前正确删除实体的父级,或者甚至不需要在删除实体之前删除(将其设置为null)父级(在某些情况下会导致问题。因此答案应该是, 没有)?

【问题讨论】:

    标签: hibernate jpa eclipselink jpa-2.1


    【解决方案1】:

    如果您有一个 NOT NULL 约束并且双向关联最好从父端传播更改:

    public boolean delete(City city) { // Detached instance.
        City managedCity = entityManager.contains(city) ? city : entityManager.merge(city);
        managedCity.getState().getCityList().remove(managedCity);
        return true;
    }
    

    并确保将 REMOVE 操作从父级级联到子级:

    @OneToMany(cascade = CascadeType.REMOVE)
    

    仅当您有一个 NULL FK 时,将父关联设置为 null 才有效。

    【讨论】:

    • 所以,我假设从关系的任一侧断开链接(关系)就足够了,即要么从关系的反面列表中删除实体,要么将实体的父级本身设置为 @ 987654323@(如果是 null 外国外国)。两者都不是必需的。是吗?
    • 设置双方是创建关联时的要求。打破它时,最好从父级级联到子级。在单向 mant-to-one 关联中,您只需删除 Child。在双向关联中,只有级联可以解决 NOT NULL FK,因为没有它,如果您只打破一侧,您可以在删除后重新连接子级。
    【解决方案2】:

    您无需从州列表中删除城市。

     public boolean delete(City city) { // Detached instance.
        City managedCity = entityManager.contains(city) ? city :    entityManager.merge(city);
        //managedCity.getState().getCityList().remove(managedCity);
        //managedCity.setState(null);
        entityManager.remove(managedCity);
        return true;
    

    }

    当状态被删除时,您可以删除所有城市

    class State {
     ...
      @OneToMany(cascade = CascadeType.REMOVE, ...)
      private List<City> cityList;
     ...
    }
    

    【讨论】:

    • 我也这么认为。但是您确定在实体本身被删​​除之前不将父引用 (managedCity.setState(null);) 设置为 null 吗?我一直在阅读一些强烈推荐的地方。 (另一方面,将需要从其父列表中删除实体 (City),因为仅删除了 City(而不是其父 State),即 cascade = CascadeType.REMOVE 位于没有被删除的关系)。
    猜你喜欢
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2021-04-04
    • 2012-09-06
    • 2014-02-13
    相关资源
    最近更新 更多