以一对多关系删除子节点抛出ObjectDeletedException

slo*_*mir 7 hibernate one-to-many

我只是不明白为什么Hibernate抛出标题中提到的异常.我可能不了解Hibernate背后的状态管理理念.

我有以下情况:

组织与员工之间的一对多关系

Organization.hmb.xml

<set name="employees" inverse="true" cascade="save-update">  
    <key column="organization_id"/>  
    <one-to-many class="Employee"/>  
</set>
Run Code Online (Sandbox Code Playgroud)

Employee.hbm.xml

<many-to-one name="organization" class="Organization"  column="organization_id" />
Run Code Online (Sandbox Code Playgroud)

我使用标准的Spring/Hibernate应用程序架构与服务和DAO,其中DAO扩展HibernateDaoSupport类并使用HibernateTemplate类的服务进行会话管理.

当我尝试在此场景中删除Employee时...

Employee e=employeeService.read(1); 

//EDIT: Important! delete operation in EmployeeService is (@)transactional  
employeeService.delete(e); //this call just delegate execution to employeeDao.delete
Run Code Online (Sandbox Code Playgroud)

编辑:我最初没有提到服务层中的删除操作是事务性的,这似乎是重要的信息(继续阅读)!

Hibernate抛出......

 ObjectDeletedException: deleted object would be re-saved by cascade...
Run Code Online (Sandbox Code Playgroud)

EmployeeService中的删除操作看起来像......

  @Transactional public void delete(Employee emp){  
    Employee e=employeeDao.read(emp.getId());  
    if(e==null)  
        throw NoSuchOrganizationException();  

    /*...several while-s to delete relations where Employee is  
    not owner of relation... */

    employeeDao.delete(e);  
}
Run Code Online (Sandbox Code Playgroud)

场景(它们没有关联):
1.当我从Organization.hbm.xml中的关系映射到Employee(s)中删除cascade ="save-update"时,一切正常.
2. 当我从删除方法中删除@Transactional注释时,一切正常.
3. 当我从子(父)(组织)子列表中删除子(Employee),然后执行删除时,一切正常.

问题:

为什么Hibernate关心父类中的级联
他认为在组织对象上级联的执行点在哪里?为什么他不能用DELETE FROM删除Employee(Child)......就是这样.此外,员工是关系的所有者,在他身上执行的操作应该管理关系本身.当他想在所提到的场景中调用组织对象的任何操作时呢?我只是不明白.

Chs*_*y76 11

你可能会丢失的是Hibernate的自动维护状态已加载并在会议存在的实体,这意味着它会持续到他们所做的任何更改irregardless的你是否显式调用"更新()"方法.

考虑到你的场景,如果你已经加载了Organization它的employees设置并且现在正试图删除其中一个员工,Hibernate告诉你(通过抛出ObjectDeletedException)它会在保存时重新保存已删除的员工,Organization因为你已经宣布保存或更新应该从组织级联到其集合中的员工.

处理此问题的正确方法是在删除employees之前从组织的集合中删除该员工,从而防止级联重新保存.

编辑(根据更新的问题):

Organization 拥有员工集合.级联始终跟随关联 - 您已将其声明为Organization侧面,因此更改(保存/更新)会向下传播到Employee级别.只要特定Employee实例是生成会话employees的任何Organization实体的集合的成员,当会话被刷新/关闭时,它将被保存(或重新保存,因此抛出异常).

Employee侧面映射关联的事实 (例如organization_id列驻留在Employee表中)与此无关; 它可以通过连接表映射到相同的结果.Hibernate通过会话维护"状态",当你试图删除Employee而不删除它时,Organization.employees你会给出Hibernate冲突指令(因为它仍然存在 - 并且必须保存 - 在一个地方但在另一个地方被删除),因此例外.