在休眠级联删除的问题
问题描述:
这个问题已被问过很多次,但我没有看到一个令人满意的答案,因此,我再次问它。在休眠级联删除的问题
想象一下以下情况:
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;
...
}
所有我想要的是删除用户。从逻辑上讲,会假设所有连接用户和位置的相关“关注者”条目都将被删除。如果我删除一个位置条目,则相同的假设应该保持在这种状态。
实际发生的事情是,Hibernate试图更新(?!?)拥有关注者的表,并且因为相关实体(用户或位置)已被发送删除,所以尝试设置外键followerId为null。这会引发异常,并破坏所有后续操作。
我得到的错误: 服务器出现未处理的故障。无法执行JDBC批处理更新; SQL [update locationstofollowers set followerId = null where followerId =?];约束[null];嵌套异常是org.hibernate.exception.ConstraintViolationException:无法执行JDBC批量更新
P.S.我听说有另一个级联选项DELETE_ORPHAN。这似乎已被废弃,即使我也尝试过,效果也是一样的。
答
既然你已经做了双向映射,你必须从两个地方删除对象。这应该工作:
user.followedLocations.remove(aLocation);
session.update(user);
session.delete(aLocation);
答
应设置@JoinColumn(name = “followerId”,插入=假,可更新= FALSE)
非常好的问题。可悲的是,在这方面没有多少讨论。 – pavanlimo 2011-08-03 12:53:59