Java – Spring Data JPA – save() method working perfectly fine without using the returned entity

hibernatejavajpaspring-dataspring-data-jpa

Below is the Javadoc specific for the save() method in Spring Data JPA

/**
 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
 * entity instance completely.
 * 
 * @param entity
 * @return the saved entity
 */
<S extends T> S save(S entity);

and also below resource clearly states that we need to use the returned objected to ensure that we perform further operations on the saved entity.

Why to use returned instance after save() on Spring Data JPA Repository?

However, in my below code my save() entity works fine without

public void createEmployee(Employee employee) throws Exception {
    try {
        employee.setEmployeeName("alan");   
        employeeRepo.save(employee);
        employee.setEmployeeType("Permanent");  
        employeeRepo.save(employee); 
    } catch (Exception e) {
        throw new Exception(e);
    }

}
  1. Why is the above code working without a return type
  2. Tests seem to show that data is being persisted perfectly fine, but i was under the impression that we need to use the returned entity to ensure correct persistence.

Am I doing something inadvertently right/wrong ? I am new to spring-data and would like to understand save() method perfectly since a lot of my current application is CRUD based. Thanks.

Best Answer

The save() method of SimpleJpaRepository is as below:

/*
 * (non-Javadoc)
 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
 */
@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

For a new entity instance it does not actually matter as the save() method returns the same instance.

Note that (assuming you have an active transaction at the service layer) your code should work even without the 2nd call to save() as the initial call to save() will delegate to EntityManager.persist() which will make the employee instance managed and tracked: any changes made to the entity within an active transaction will be automatically flushed to the database on transaction commit (See further : http://www.objectdb.com/java/jpa/persistence/managed).

public void createEmployee(Employee employee) throws Exception {
    try {
        employee.setEmployeeName("alan");   
        employeeRepo.save(employee);
        employee.setEmployeeType("Permanent");  
        //employeeRepo.save(employee); <- not required : type should still be 'Permanent' in DB.
    } catch (Exception e) {
        throw new Exception(e);
    }

}