Tiny
Tiny

Reputation: 27899

Before deleting an entity, deleting its parent reference(s), if any

It is essential to delete an entity from its parent list and the parent from the entity itself before the entity is deleted.

Example (CMT in an EJB) one-to-many from State to City :

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

The statement managedCity.setState(null); sets the entity's parent to null. Since it is a managed entity, any changes made to the entity will hit the underlying database. Accordingly, an UPDATE statement will be generated and state_id in the database table will be set to null.

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

This is quite undesired. In addition to issuing an addition UPDATE statement, it attempts to set state_id in the database table to null which will cause problems, if a NOT NULL database constraint is enforced against the corresponding column in the database table.

How to correctly remove entity's parent before deleting the entity itself or it is not even required to delete (setting it to null) the parent before deleting the entity (it would cause problems in some cases. The answer should therefore be, No)?

Upvotes: 4

Views: 1561

Answers (2)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 154030

In case you have a NOT NULL constraint and a bidirectional association is better to propagate the change from the parent side:

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

and make sure you cascade the REMOVE operation from Parent to Child:

@OneToMany(cascade = CascadeType.REMOVE)

Setting the parent association to null only works when you have a NULL FK.

Upvotes: 2

vels4j
vels4j

Reputation: 11298

You need not delete city from state list.

 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;

}

you can delete all the cities when state is removed

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

Upvotes: 1

Related Questions