Removing a child in a one-to-many relationship throws an ObjectDeletedException

I just don't understand why Hibernate throws the exception indicated in the header. I probably do not understand the idea of ​​governing the state behind Hibernate.

I have the following situation:

One-to-Many Relationship Between Organization and Employee

Organization.hmb.xml

<set name="employees" inverse="true" cascade="save-update"> <key column="organization_id"/> <one-to-many class="Employee"/> </set> 

Employee.hbm.xml

 <many-to-one name="organization" class="Organization" column="organization_id" /> 

I use the standard Spring / Hibernate application architecture with services and DAOs, where DAOs extend the HibernateDaoSupport class and use the services of the HibernateTemplate class to manage sessions.

When I try to remove Employee in this scenario ...

 Employee e=employeeService.read(1); //EDIT: Important! delete operation in EmployeeService is (@)transactional employeeService.delete(e); //this call just delegate execution to employeeDao.delete 

EDIT . At the beginning, I did not mention that the delete operation in the Service layer is transactional, which seems to be important information (keep reading)!

Sleep mode throws ...

  ObjectDeletedException: deleted object would be re-saved by cascade... 

Deleting an operation in an EmployeeService looks like ...

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

Scenarios (they are not related):
1. When I remove cascade = "save-update" from the relationship mapping with Employee (s) in Organization.hbm.xml, everything works fine .
2. When I delete the @Transactional annotation from the delete method, everything works fine.
3. When I delete the child (Employee) from the parent (Organization) list of children , and then do the deletion, everything works fine.

Question :

Why does Hibernate even care about the cascade in the parent class ?
Where is the execution point at which it considers the cascade of the Organization object ? Why can't he just delete Employee (Child) with DELETE FROM ... and what is he. In addition, Employee is the owner of the relationship, and the operations it performs must manage the relationship itself. When did he think that all operations on the Organization object in the specified script anyway ? I just do not understand.

+7
source share
1 answer

What you may be missing is that Hibernate automatically saves state for objects that have been loaded and exist in the session, which means that it will save any changes made to them whatever if you explicitly call "update" () "

Given your scenario, if you loaded Organization and its employees and are now trying to delete one of these employees, Hibernate tells you (throwing ObjectDeletedException ) that it will re-save the remote employee when it saves Organization , because you stated that the save or update should be cascaded from organization to employees in their recruitment.

The right way to handle this would be to remove the employee from the organization before removing it, thereby preventing the cascade from being saved again.

Edit (based on updated question):

Organization owns a collection of employees. The cascade always follows the association - you declared it on the Organization side, so changes (save / update) propagate to the Employee level. As long as a particular instance of Employee is a member of the employees collection of any Organization object that lives in the session, it will be saved (or re-saved, so an exception is thrown) when the session is cleared / closed.

The fact that the association is displayed on the Employee side (for example, the organization_id column is in the Employee table) does not matter here; it could be matched through a connection table with the same results. Hibernate maintains state through the session, and when you try to delete Employee without deleting it from Organization.employees , you provide conflicting Hibernate instructions (since it is still alive and needs to be saved) in one place, but deleted in another), therefore an exception.

+11
source

All Articles