你这犯了一个严重的Hibernate中关联对象删除时没有按照正确到步骤而带来到后果,Hibernate为我们提供了对象间到关联操作,对于增加、更新都是很自然的,你更新一个对象到set中元素,那么set中到对象属性也会自动同步到数据库,但是对于删除操作Hibernate却不会这样做,因为删除对于数据库来说是一种谨慎行为,数据一旦删了可能带来很严重后果(特别是你在利用Hibernate到关联操作来到达删除对象到时候,也许某个操作你是不小心的,如你设置set中某些元素为null,而这个动作并不是有意到,如果Hibernate级联去删除到话造成麻烦),所以Hibernate还是作出以下机制:当你想要删除某个对象时,你应该直接去删除这个对象,而不是通过级联的形式,当然你也应该包括把set中的相应元素至为null(这个元素就是你要删除到真正到对象),这才是删除的正确形式。
对于有多方的删除操作,我们应该直接操作要删除的实体使用delete方法,而不要使用one端的set属性进行移除操作就能到达这种目的的想法是不对的,但是在设置了cascade的地方,这种思想必须得到使用,因为用了cascade的地方,会在flush时查看set的集合内容。
对于主表删除要合理使用cascade,除非你不想主表记录删除后辅表关联记录还存在。
如下面这种操作形式以及正确的做法。
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c);
c.setParent(null);
session.flush();
will not remove c from the database; it will ony remove the link to p (and cause a NOT NULL constraint violation, in this case). You need to explicitly delete() the Child.
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c);
session.delete(c);
session.flush();
其实所谓cascade在同步点如flush,call会同步缓存和数据库的数据,但只要能让数据合理解释就行,Hibernate不应该去主动删除数据,其实p.getChildren().remove(c);c.setParent(null);仅仅说明他们之间的关系解除,而并不能告诉Hibernate足够信息说我要删除c,否则可能导致数据丢失带来灾难,所以要删除数据还是要手动调用delete,而如果你增加了set,在同步缓存时明显数据库中会缺少相应的记录,理应加上相应的记录。
但是如果想删除不在set中的关联实体,即上面第一种形式正确,可以设置<set cascade="all-delete-orphan"来到达当set中元素不再被关联时删除。
嗫?暁雲?