Skillversitas

CRUD Operations

Introduction

CRUD (Create, Read, Update, Delete) is the set of fundamental data-management operations. Learn a complete CRUD implementation using controllers, services, and repositories.

Entity

@Entity
@Table(name = "product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Product name is required")
    @Size(max = 200)
    private String name;

    private String description;

    @Min(value = 0, message = "Price cannot be negative")
    private double price;

    private int stock;

    @Column(name = "created_at")
    private LocalDateTime createdAt;

    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
}

Repository

public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByNameContaining(String keyword);
    boolean existsByName(String name);
}

Service Layer

@Service
public class ProductService {

    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    // CREATE
    public Product create(Product product) {
        if (productRepository.existsByName(product.getName())) {
            throw new BadRequestException("A product with that name already exists");
        }
        return productRepository.save(product);
    }

    // READ ALL
    public List<Product> findAll() {
        return productRepository.findAll();
    }

    // READ BY ID
    public Product findById(Long id) {
        return productRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("Product not found"));
    }

    // UPDATE
    public Product update(Long id, Product updatedData) {
        Product product = findById(id);
        product.setName(updatedData.getName());
        product.setDescription(updatedData.getDescription());
        product.setPrice(updatedData.getPrice());
        product.setStock(updatedData.getStock());
        return productRepository.save(product);
    }

    // DELETE
    public void delete(Long id) {
        Product product = findById(id);
        productRepository.delete(product);
    }
}

Controller

@RestController
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Product create(@Valid @RequestBody Product product) {
        return productService.create(product);
    }

    @GetMapping
    public List<Product> findAll() {
        return productService.findAll();
    }

    @GetMapping("/{id}")
    public Product findById(@PathVariable Long id) {
        return productService.findById(id);
    }

    @PutMapping("/{id}")
    public Product update(@PathVariable Long id, @Valid @RequestBody Product product) {
        return productService.update(id, product);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        productService.delete(id);
    }
}

Endpoint Summary

Method Endpoint Purpose Status Code
POST /api/products Create a new product 201
GET /api/products Fetch all products 200
GET /api/products/{id} Fetch a product by ID 200
PUT /api/products/{id} Update a product 200
DELETE /api/products/{id} Delete a product 204

Request Flow

Client → Controller → Service → Repository → Database
          ↓
    Input validation
          ↓
    Error handling

Summary

  • Separate the code: Controller (HTTP), Service (business), Repository (data).
  • Use @Valid for input validation.
  • The service layer handles business logic and business validation.

Next chapter: We'll cover Pagination & Sorting — how to manage large volumes of data with pagination and sorting.