CRUD Methods

Methods You Get for Free

MethodReturnsSQL (roughly)
save(entity)saved entityINSERT or SELECT + UPDATE
saveAll(list)List<T>many INSERT/UPDATE
findById(id)Optional<T>select ... where id=?
existsById(id)booleanselect count(*) ... where id=?
findAll()List<T>select ... from products
findAll(Sort.by("price"))List<T>... order by price
findAllById(ids)List<T>... where id in (?,?,?)
count()longselect count(*)
deleteById(id)voidSELECT then DELETE
delete(entity)voidDELETE
getReferenceById(id)proxyno SQL until used

Using Them

Product saved = productRepository.save(
        new Product("SKU-BOAT-450", "Boat Rockerz 450", new BigDecimal("1499.00"), 120, "Electronics"));

Product p = productRepository.findById(42L)
        .orElseThrow(() -> new ProductNotFoundException(42L));

List<Product> all = productRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
long total = productRepository.count();
productRepository.deleteById(42L);

Request and SQL

Calling the controller that wraps findById:

curl localhost:8080/api/products/42

Example output

Hibernate: select p1_0.id,p1_0.category,p1_0.created_at,p1_0.description,p1_0.name,p1_0.price,p1_0.sku,p1_0.status,p1_0.stock from products p1_0 where p1_0.id=?

HTTP/1.1 200 OK
Content-Type: application/json
{"id":42,"sku":"SKU-BOAT-450","name":"Boat Rockerz 450","price":1499.00,"stock":120,"category":"Electronics","status":"ACTIVE"}

How save() Works

save is implemented in SimpleJpaRepository roughly like this:

@Transactional
public <S extends T> S save(S entity) {
    if (entityInformation.isNew(entity)) {   // id == null (or @Version == null)
        entityManager.persist(entity);
        return entity;
    } else {
        return entityManager.merge(entity);   // returns a DIFFERENT (managed) instance
    }
}
  • New entity (id null) → persist → INSERT.
  • Entity with an id → merge → SELECT + UPDATE (or INSERT if the row does not exist).
  • Always use the returned object: product = repo.save(product);
  • Inside a @Transactional method, a managed entity does not need save at all — dirty checking saves it. Calling it anyway is harmless.
  • Repository methods are transactional on their own; findById methods are readOnly = true.