0

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.

Community
  • 1
  • 1
HopeKing
  • 2,574
  • 3
  • 34
  • 54

1 Answers1

2

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

}
Alan Hay
  • 20,941
  • 2
  • 47
  • 97
  • 1. "For a new entity instance it does not actually matter as the save() method returns the same instance" -> Can you please clarify....in what situations is a difference instance created ? 2. What do you mean by "active transaction" ....I am using Spring Data and since the transactions are being managed by Spring Data, i am probably confused. Everyone speaks of active transaction, what exactly is it in Spring Data context ? Thanks – HopeKing Apr 20 '17 at 13:51
  • You really need to understand the underlying JPA API as Spring Data is of course only an abstraction over this `EntityManager.merge(..)` vs `EntityManager.persist(..)`. **Point 1**: when you are updating an existing instance: http://stackoverflow.com/a/1070629/1356423 **Point 2**. Transactions are typically defined at the service layer: http://stackoverflow.com/a/19723602/1356423 – Alan Hay Apr 20 '17 at 14:04
  • Many thanks for the excellent resources. Also, Why is my above code working without a Return type in Save ? – HopeKing Apr 20 '17 at 14:45