Problems with cascading deletion in Hibernate
This question has been asked numerous times before, yet I haven't seen a satisfactory answer since, thus I am asking it again.
Imagine the following situation:
public class User {
...
@Cascade(value= {CascadeType.DELETE})
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="followerId")
public List<LocationFollower> followedLocations;
...
}
public class LocationFollower {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
public Long id;
@ManyToOne
@JoinColumn(name="locationId")
public Location followedLocation;
@ManyToOne
@JoinColumn(name="followerId")
public User follower;
@Column(name = "followerSince")
public Timestamp followerSince;
}
public class Location {
...
@Cascade(value = {CascadeType.DELETE})
@OneToMany(fetch= FetchType.LAZY)
@JoinColumn(name="locationId")
public List<LocationFollower> followers;
...
}
All I wanted was to delete a user. Logically, one will assume all related "follower" entries connecting User and 开发者_如何学JAVALocation will be deleted. The same assumption should stay in power if I delete a Location entry.
What happens actually is that Hibernate tries to update (?!?) the table that holds the followers, and since the related entity (User or Location) has been sent for deletion, tries to set a foreign key, for instance, followed with null. This throws an exception and burst all the succeeding operations.
The error I get: There was an unhandled failure on the server. Could not execute JDBC batch update; SQL [update locationstofollowers set followerId=null where followerId=?]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
P.S. I hear that there was another cascade option DELETE_ORPHAN. This seems to be deprecated, and even though I tried it as well, the effect was the same.
Since you have made a bi-directional mapping, you have to remove the object from both places. This should work:
user.followedLocations.remove(aLocation);
session.update(user);
session.delete(aLocation);
You should set @JoinColumn(name="followerId", insertable = false, updatable = false)
精彩评论