Логотип Workflow

Article

Updated at:

Crud Operations

Stage 4 - CRUD Operations: Create, Read, Update, Delete

CRUD is not just four repository calls; it is the basic data lifecycle wrapped in validation, errors, and transactions. Most business features combine Create, Read, Update, and Delete with validation, authorization, transactions, and domain rules. In Spring Data JPA, repositories provide the low-level CRUD methods, while services decide how those methods are used safely.

CRUD service flow

Create and Read

Create means inserting a new record. In Java code, you usually create an entity object, fill required fields, validate business rules, and call save. Hibernate generates an insert when the object has no database identity yet.

public User createUser(CreateUserRequest request) {
    User user = new User(request.email(), request.name());
    return userRepository.save(user);
}

Read means loading data. Reading by id uses findById. Reading a list can use findAll, but production APIs should normally use pagination. Pageable describes page number, page size, and sorting. Page<T> contains the content and metadata such as total elements and total pages.

public Page<Product> listProducts(Pageable pageable) {
    return productRepository.findAll(pageable);
}

Update

Update should usually start by loading the existing entity. This matters because the database row may not exist, and because the current state may be needed for validation. After loading the entity inside a transaction, change its fields. Hibernate tracks managed entities and flushes changes at commit.

@Transactional
public User renameUser(Long id, String name) {
    User user = userRepository.findById(id)
        .orElseThrow(() -> new EntityNotFoundException("User not found: " + id));
    user.setName(name);
    return user;
}

Calling save after changing a managed entity is often not required, but many teams still do it for explicitness. The important point is to avoid updating by creating a new object with only an id and a few fields unless you understand merge behavior. That approach can accidentally overwrite fields with null.

Delete and service layer

Delete removes data. deleteById is concise, but for business operations it is often better to load first, check rules, and then call delete. For example, deleting a product may be forbidden if it has completed orders. Such rules belong in the service layer, not in the controller.

Controllers should translate HTTP input and output. Services should coordinate use cases. Repositories should persist entities. If CRUD code is placed directly in controllers, error handling, validation, and transactions become scattered.

CRUD scenarioCorrect service flowCommon beginner mistake
Create a userValidate request, create a new entity, set defaults, call save.Trusting request fields directly and forgetting required defaults such as createdAt.
Read one userCall findById, convert empty Optional to a domain error or HTTP 404.Calling .get() and producing a vague runtime exception.
Read product listAccept Pageable, choose sorting, return DTO page.Calling findAll() and loading the whole table for one screen.
Update product priceLoad existing entity, check rules, change fields inside a transaction.Creating a new partial entity and accidentally overwriting fields with null.
Delete recordLoad entity, verify deletion is allowed, then delete.Deleting by id without checking ownership, status, or dependent records.

Error handling

EntityNotFoundException or a custom exception makes missing data explicit. In a REST API, the exception can be mapped to HTTP 404 by a @ControllerAdvice. Custom exceptions are often better when the domain language matters, such as UserNotFoundException or ProductNotFoundException.

Errors should not be swallowed. If an update target does not exist, the API should not silently create another row unless the feature explicitly supports upsert. Clear failures make clients easier to debug and prevent hidden data corruption.

Practice

Implement CRUD for users and products. For users, create endpoints to create, get by id, list with pagination, rename, and delete. For products, include price and availability updates. Keep controllers thin: they call services and return DTOs. Put @Transactional on service methods that modify data. Test missing ids and verify that they produce a predictable error response.

Understanding checklist

  • I can explain Create, Read, Update, and Delete in JPA terms.
  • I know why update usually begins with findById.
  • I understand Pageable and Page.
  • I know why controllers should not contain CRUD business logic.
  • I can design a clear not-found error flow.

Please login to pass quizzes.

Practice

Interactive practice

Complete tasks and check your answer instantly.