Search code examples
javahibernate

Behaviour of persisting the object in hibernate


I am trying to delete the entity using hibernate. Assume there is only one record in the database and I am using the EntityManger remove() method to delete the record.

    @Transactional
    public void deleteEmployee(Long id) {
        for (int i = 0; i < 3; i++) {
            Employee result = (Employee) employeeDao.findEmployeeById(id);
            employeeDao.deleteEmployee(result);
            employeeDao.deleteEmployee(result);

        }
    }


In this code above, I am deleting the employee only the first iterations, Since I am deleting using this two times employeeDao.deleteEmployee(result); in first iteration only it is not throwing the error. Now in second code.

    @Transactional
    public void deleteEmployee(Long id) {
        for (int i = 0; i < 3; i++) {
            Employee result = (Employee) employeeDao.findEmployeeById(id);
            employeeDao.deleteEmployee(result);

        }
    }

Whereas in in my another code I am deleting the employee using the two iterations, First iteration it delete the employee record, then in second iteration it try to delete the record but get the error org.springframework.dao.InvalidDataAccessApiUsageException: attempt to create delete event with null entity

My understanding: I first get the employee using the findEmployeeById(id);. It fetch it from the database and pull it into the RAM memory. Now if i delete it, it get removed from RAM memory, but not persist to the database as my transaction method is not completed. Now if i again delete the record from second iterations, it return the record from the RAM memory not from the database, as it was already there in RAM memory, so it will return no record and when i try to delete it throw error.

While in the case of deleting the employee calling the employeeDao.deleteEmployee(result); two times in same iterations, first time it mark for deletion and second time again it mark for deletion thus no error.

I am bit skeptical about my understanding, Please help in better way and also tell me if i am correct.


Solution

  • First things to have in mind : your method is transactional, so no action is persisted unless the transaction finishes correctly. And also, EntityManager does not act instantly on the DB, it sort of "marks" the entities in multiple states, and then after "flush" it acts on the DB.

    Now about your code snippets: in your first one, it is not throwing in the first iteration because you hold a reference to an existing employee entity, it does not matter if you apply remove multiple times as long as the reference is not null (the reference being here "result" variable. The first call would be effective, the other calls get ignored as the state is already deleted).

    In the second code snippet, the first iteration goes ok, but in the second iteration you try to lookup an entity that is "marked" to be deleted after transaction finishes, which mean your dao will return null, which means you pass null to your deleteEmployee method.

    May be taking a look at jpa entity lifecycle statuses would help you clarify things more. Here is a medium short article about that : JPA entity lifecycle