在删除实体之前,删除其父引用(如果有)

时间:2015-07-08 03:39:32

标签: hibernate jpa eclipselink jpa-2.1

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

示例(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)父级(在某些情况下会导致问题。答案应该是因此,)?

2 个答案:

答案 0 :(得分:2)

如果您有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操作从Parent级联到子级:

@OneToMany(cascade = CascadeType.REMOVE)

将父关联设置为null仅在具有NULL FK时才有效。

答案 1 :(得分:1)

您无需从州名单中删除城市。

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