How does save method of CrudRepository class work internally?

It just a wrapper of operations of entity manager.

The implementation in SimpleJpaRepository:

@Transactional
@Override
public <S extends T> S save(S entity) {
 
	Assert.notNull(entity, "Entity must not be null");
 
	if (entityInformation.isNew(entity)) {
		em.persist(entity);
		return entity;
	} else {
		return em.merge(entity);
	}
}

The variable entityInformation is of type EntityInformation and is used for querying information of entity.

The implementation of isNew method in AbstractEntityInformation that is the implementation of EntityInformation interface:

public boolean isNew(T entity) {
 
  ID id = getId(entity);
  Class<ID> idType = getIdType();
 
  if (!idType.isPrimitive()) {
	return id == null;
  }
 
  if (id instanceof Number) {
	return ((Number) id).longValue() == 0L;
  }
 
  throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType));
}

As we can see, when checking the new state of an entity, the framework will:

  • Check whether the type of ID is primitive. If it is not primitive (non-primitive), compare with null.
    • If it is null: is new.
    • If not: is not new.
  • If it is primitive and is a number, convert to Number and get the long value then compare to 0.
    • If it is equal to 0: is new.
    • If not: is not new.
  • Otherwise: throw exception about wrong type of ID.

About persist and merge:

  • persist is used when we want to create a whole new record of an object in database.
  • merge is used when we want to update changes of a recoed in database.

Those methods are implemented in SessionImpl class which is the implementation of Session interface. And Session interface is a sub interface of EntityManager interface. In other words, those methods are used to perform actions on a persistence context (Session in this case) of an ORM (Hibernate).

Resources