← Volver

CRUD en Spring Boot

Publicado el 29 de enero de 2026

Primero crearemos la estructura del proyecto de la siguiente manera:

Ahora veremos el código de cada fichero.

En Product.java

package com.ccorreas.curso.java.springboot.backend.__springboot_backend.entities;

import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String description;
    private Long price;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Long getPrice() {
        return price;
    }

    public void setPrice(Long price) {
        this.price = price;
    }
}

ProductRepository.java

package com.ccorreas.curso.java.springboot.backend.__springboot_backend.repositories;

import com.ccorreas.curso.java.springboot.backend.__springboot_backend.entities.Product;
import org.springframework.data.repository.CrudRepository;

public interface ProductRepository extends CrudRepository<Product, Long> {
}

ProductService.java

package com.ccorreas.curso.java.springboot.backend.__springboot_backend.services;

import com.ccorreas.curso.java.springboot.backend.__springboot_backend.entities.Product;

import java.util.List;
import java.util.Optional;

public interface ProductService {
    List<Product> findAll();
    Optional<Product> findById(Long id);
    Product save(Product product);
    Optional<Product> deleteById(Long id);
}

ProductServiceImpl.java

package com.ccorreas.curso.java.springboot.backend.__springboot_backend.services;

import com.ccorreas.curso.java.springboot.backend.__springboot_backend.entities.Product;
import com.ccorreas.curso.java.springboot.backend.__springboot_backend.repositories.ProductRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
public class ProductServiceImpl implements ProductService{
    final private ProductRepository repository;

    public ProductServiceImpl(ProductRepository repository) {
        this.repository = repository;
    }

    @Transactional(readOnly = true)
    @Override
    public List<Product> findAll() {
        return (List<Product>) repository.findAll();
    }

    @Transactional(readOnly = true)
    @Override
    public Optional<Product> findById(Long id) {
        return repository.findById(id);
    }

    @Transactional
    @Override
    public Product save(Product product) {
        return repository.save(product);
    }

    @Transactional
    @Override
    public Optional<Product> deleteById(Long id) {
        Optional<Product> productOptional = repository.findById(id);

        if(productOptional.isPresent()){
            repository.deleteById(id);
            return productOptional;
        }

        return Optional.empty();
    }
}

ProductController.java

package com.ccorreas.curso.java.springboot.backend.__springboot_backend.controllers;

import com.ccorreas.curso.java.springboot.backend.__springboot_backend.entities.Product;
import com.ccorreas.curso.java.springboot.backend.__springboot_backend.services.ProductService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
public class ProductController {

    final private ProductService service;

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

    @GetMapping
    public ResponseEntity<List<Product>> list(){
        return ResponseEntity.ok(service.findAll());
    }

    @GetMapping("/{id}")
    public ResponseEntity<Product> details(@PathVariable Long id){
        Optional<Product> optionalProduct = service.findById(id);

        if(optionalProduct.isPresent()){
            return ResponseEntity.ok(optionalProduct.orElseThrow());
        }

        return ResponseEntity.notFound().build();
    }

    @PostMapping
    public ResponseEntity<Product> create(@RequestBody Product product){
        return ResponseEntity.status(HttpStatus.CREATED).body(service.save(product));
    }

    @PutMapping("/{id}")
    public ResponseEntity<Product> update(@RequestBody Product product, @PathVariable Long id){
        Optional<Product> optionalProduct = service.findById(id);

        if(optionalProduct.isPresent()){
            Product productDb = optionalProduct.orElseThrow();
            productDb.setDescription(product.getDescription());
            productDb.setName(product.getName());
            productDb.setPrice(product.getPrice());
            return ResponseEntity.status(HttpStatus.CREATED).body(service.save(productDb));
        }

        return ResponseEntity.notFound().build();
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Product> delete(@PathVariable Long id){
        Optional<Product> optionalProduct = service.findById(id);

        if(optionalProduct.isPresent()){
            Product productDelete = service.deleteById(id).orElseThrow();
            return ResponseEntity.status(HttpStatus.OK).body(productDelete);
        }

        return ResponseEntity.notFound().build();
    }
}