Contenido del curso
Primeros pasos
Spring Data Repositories
- 7

Qué son los Spring Data Repositories
08:39 min - 8

Guardar y Actualizar Registros con Spring Data Repositories
08:34 min - 9

Eliminar elementos con Spring Data JPA: método deleteById
05:36 min - 10

Lazy vs Eager en relaciones JPA
15:09 min - 11

Query Methods en Spring para Consultas Personalizadas
08:27 min - 12

Filtrar pizzas con Containing y Not en JPA
07:27 min - 13

Fechas y listas en query methods de JPA
11:25 min - 14

findTop y Optional en Spring Data JPA
09:30 min - 15

Paginación y Ordenación con Spring Data Repositories
07:39 min - 16

Ordenamiento Dinámico con Paging and Sorting Repository
07:58 min
Personalización de queries
Características avanzadas
Próximos pasos
@Modifying para updates con @Query en JPA
Resumen
Modificar datos en una base de datos con Spring Data JPA va más allá de un simple save(). Cuando necesitas ejecutar un update, insert o delete desde una consulta personalizada, la anotación @Modifying se vuelve indispensable. Aquí aprenderás a combinarla con @Query para actualizar el precio de una pizza usando SQL nativo y Spring Expression Language.
¿Cómo crear un DTO para transferir datos en Spring Boot?
Antes de tocar el repositorio, necesitas un objeto que transporte la información entre capas. Un Data Transfer Object (DTO) cumple justo esa función: encapsular los datos que viajan desde el cliente hasta tu servicio.
Dentro del paquete service.dto creas la clase UpdatePizzaPriceDTO y la anotas con @Data de Lombok para generar automáticamente getters, setters y constructores [01:00]. Los atributos son simples:
private Integer pizzaIdpara identificar la pizza.private double newPricepara el precio actualizado.
¿Qué es un DTO en Spring Boot? Es una clase que transporta datos entre capas sin lógica de negocio. Se usa para recibir o enviar información estructurada, como el ID de una pizza y su nuevo precio.
¿Cómo escribir un UPDATE con @Query y @Modifying?
En PizzaRepository defines un método updatePrice que no retorna nada. Lo anotas con @Query indicando que es una consulta nativa y construyes el SQL paso a paso [02:10]:
java @Modifying @Query(value = "UPDATE pizza " + "SET price = :#{#newPizzaPrice.newPrice} " + "WHERE id_pizza = :#{#newPizzaPrice.pizzaId}", nativeQuery = true) void updatePrice(@Param("newPizzaPrice") UpdatePizzaPriceDTO newPizzaPrice);
Fíjate en el detalle: cada línea termina con un espacio antes de las comillas para que Java concatene el SQL sin pegar palabras. Es un error silencioso muy común.
¿Qué es Spring Expression Language y cómo se usa en @Query?
En lugar de pasar dos parámetros sueltos, puedes recibir el DTO completo y extraer sus atributos dentro de la consulta. Para eso usas SpEL con la sintaxis :#{#nombreParametro.atributo} [03:30].
Esto te permite:
- Reducir la firma del método a un solo parámetro.
- Acceder a cualquier campo del objeto desde el SQL.
- Mantener el código más limpio cuando trabajas con objetos compuestos.
No es obligatorio. Puedes seguir usando @Param tradicional con parámetros individuales, pero conocer SpEL te da flexibilidad cuando manejas objetos con varios atributos.
¿Por qué necesitas @Modifying y @Transactional juntas?
Aquí viene la parte que suele tropezar a quienes empiezan. Si solo pones @Query con un update, Spring lanza una excepción al ejecutarlo. La razón es simple: un @Query sin @Modifying solo puede hacer selects.
¿Cuándo usar @Modifying en Spring Data JPA? Siempre que tu
@Queryejecute insert, update o delete. Sin esta anotación, Spring asume que la consulta es de lectura y rechaza la operación.
Pero con @Modifying no basta. Al ejecutar la primera petición aparece otro error 500 que pide envolver la operación en una transacción [07:15]. La solución es anotar el método del servicio con @Transactional de org.springframework.transaction.annotation:
java @Transactional public void updatePrice(UpdatePizzaPriceDTO dto) { pizzaRepository.updatePrice(dto); }
Cuidado con el import. Existen varias anotaciones @Transactional en el ecosistema Java y debes elegir la de Spring Framework.
¿Cómo exponer el endpoint de actualización en el controlador?
En PizzaController agregas un método PUT que escucha en /price. Antes de actualizar, validas que la pizza exista usando el método exists que ya construiste:
java @PutMapping("/price") public ResponseEntity<Void> updatePrice(@RequestBody UpdatePizzaPriceDTO dto) { if (this.pizzaService.exists(dto.getPizzaId())) { this.pizzaService.updatePrice(dto); return ResponseEntity.ok().build(); } return ResponseEntity.badRequest().build(); }
La lógica es directa: si la pizza existe, actualiza y responde 200 OK. Si no, devuelve 400 Bad Request.
¿Cómo probar el endpoint con Postman?
Para verificar que todo funcione, envías una petición PUT al endpoint /api/pizzas/price con un cuerpo JSON [09:20]:
{ "pizzaId": 7, "newPrice": 19.99 }
La pizza con ID 7, llamada Mother Heart, pasa de costar 19.5 a 19.99. Si vuelves a consultar /api/pizzas/7, el precio refleja el cambio. En la consola verás dos consultas ejecutándose en orden: primero el count del exists y luego el update que escribiste con @Modifying.
Con esto ya puedes escribir cualquier operación de modificación dentro de un @Query. ¿Has intentado combinar SpEL con consultas más complejas? Cuéntame en los comentarios cómo lo resolverías.