在删除实体之前,必须从其父列表中删除实体,并从实体本身删除父实体。
示例(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
)父级(在某些情况下会导致问题。答案应该是因此,否)?
答案 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;
...
}