++Spring Data JPA++
adjunto un link acerca de las propagación de las transacciones como para entender un poco más
Transaction Propagation and Isolation in Spring @Transactional
Cuando trabajas con bases de datos en Spring, necesitas garantizar que cada operación se complete sin dejar datos a medias. La anotación @Transactional en Spring Data te permite cumplir con las propiedades ACID y proteger la integridad de tu información en escenarios reales como actualizar precios, guardar entidades o enviar notificaciones.
Qué son las propiedades ACID en una transacción
Una transacción confiable debe cumplir cuatro características que aseguran que los datos lleguen completos y consistentes a la base de datos.
¿Qué significa ACID en bases de datos? Es el acrónimo de Atomicidad, Consistencia, Aislamiento y Durabilidad. Son las cuatro propiedades que toda transacción debe cumplir para considerarse confiable.
Cómo funciona la anotación @Transactional en Spring Data
Con solo anotar un método con @Transactional, Spring se encarga de envolver todas las operaciones de base de datos dentro de una misma transacción atómica [1:55].
La regla práctica es simple: siempre que un método tenga dos o más llamadas a la base de datos, anótalo con @Transactional. Así te aseguras de que las operaciones se ejecuten secuencialmente como una sola unidad.
Imagina que actualizas el precio de una pizza y luego ejecutas un pizzaRepository.save() para guardar otra entidad. Si el save falla, el precio ya modificado quedaría inconsistente. Con @Transactional, ese error dispara un rollback automático que devuelve todo al estado anterior.
Ejemplo práctico con una excepción personalizada
Para probar el comportamiento, se crea un paquete exception dentro del paquete service y dentro una clase que extiende de RuntimeException [3:25]:
java public class EmailAPIException extends RuntimeException { public EmailAPIException() { super("Error sending email"); } }
Luego, un método privado sendEmail() lanza esa excepción justo después de actualizar el precio:
java private void sendEmail() { throw new EmailAPIException(); }
Al ejecutar un PUT para cambiar el precio de la pizza con ID 7 de $20 a $19.90, la API responde con un error 500 Internal Server Error. Al consultar de nuevo el precio, sigue siendo $20: el rollback funcionó porque ambas operaciones viven dentro de la misma transacción [4:50].
Cuándo usar noRollbackFor y rollbackFor
No siempre quieres que todo se revierta. Si enviar un email falla, ¿debería eso impedir que el precio se actualice? Probablemente no, porque son procesos independientes.
Para estos casos, @Transactional ofrece dos parámetros clave:
java @Transactional(noRollbackFor = EmailAPIException.class) public void updatePrice(...) { // actualizar precio sendEmail(); }
Al repetir la prueba con esta configuración, sigues recibiendo el error 500 por el email fallido, pero el precio de la pizza sí cambia en la base de datos [6:15]. Justo el comportamiento que necesitas cuando una operación secundaria no debe bloquear la principal.
¿Cuál es la diferencia entre rollbackFor y noRollbackFor?
rollbackForindica qué excepciones deben revertir la transacción;noRollbackForindica cuáles deben permitir el commit aunque se lancen.
Qué es la propagación en @Transactional y para qué sirve
La propiedad propagation define cómo se comporta un método transaccional cuando ya existe (o no) una transacción activa.
El valor por defecto es Required: si hay una transacción en curso, el método se une a ella; si no la hay, Spring crea una nueva automáticamente.
Otro valor común es Mandatory: exige que ya exista una transacción para ejecutar el método. Si no hay ninguna, lanza una excepción en lugar de crearla.
¿Qué hace propagation = Required en Spring? Es el comportamiento por defecto: usa la transacción existente si la hay, o crea una nueva si no existe ninguna.
Existen más tipos de propagación (Supports, Never, Nested, entre otros) y vale la pena revisar la documentación oficial para entender cada caso de uso.
Buenas prácticas al trabajar con transacciones en Spring
Usar @Transactional no es opcional cuando manejas operaciones críticas. Algunas recomendaciones que se desprenden de la clase:
@Transactional cualquier método que ejecute dos o más llamadas a la base de datos.noRollbackFor para excepciones de servicios externos (como envío de emails) que no deberían afectar la persistencia principal.rollbackFor cuando trabajes con excepciones checked que por defecto Spring no revierte.Required para la mayoría de los casos, Mandatory cuando exiges contexto transaccional previo.Con esto, tu proyecto Spring Data JPA queda más robusto y preparado para escalar. ¿Has tenido algún caso donde un rollback inesperado te haya causado problemas en producción? Cuéntame en los comentarios cómo lo resolviste.
Cuando trabajas con bases de datos en Spring, necesitas garantizar que cada operación se complete sin dejar datos a medias. La anotación @Transactional en Spring Data te permite cumplir con las propiedades ACID y proteger la integridad de tu información en escenarios reales como actualizar precios, guardar entidades o enviar notificaciones.
Una transacción confiable debe cumplir cuatro características que aseguran que los datos lleguen completos y consistentes a la base de datos.
¿Qué significa ACID en bases de datos? Es el acrónimo de Atomicidad, Consistencia, Aislamiento y Durabilidad. Son las cuatro propiedades que toda transacción debe cumplir para considerarse confiable.
Con solo anotar un método con @Transactional, Spring se encarga de envolver todas las operaciones de base de datos dentro de una misma transacción atómica [1:55].
La regla práctica es simple: siempre que un método tenga dos o más llamadas a la base de datos, anótalo con @Transactional. Así te aseguras de que las operaciones se ejecuten secuencialmente como una sola unidad.
Imagina que actualizas el precio de una pizza y luego ejecutas un pizzaRepository.save() para guardar otra entidad. Si el save falla, el precio ya modificado quedaría inconsistente. Con @Transactional, ese error dispara un rollback automático que devuelve todo al estado anterior.
Para probar el comportamiento, se crea un paquete exception dentro del paquete service y dentro una clase que extiende de RuntimeException [3:25]:
java public class EmailAPIException extends RuntimeException { public EmailAPIException() { super("Error sending email"); } }
Luego, un método privado sendEmail() lanza esa excepción justo después de actualizar el precio:
java private void sendEmail() { throw new EmailAPIException(); }
Al ejecutar un PUT para cambiar el precio de la pizza con ID 7 de $20 a $19.90, la API responde con un error 500 Internal Server Error. Al consultar de nuevo el precio, sigue siendo $20: el rollback funcionó porque ambas operaciones viven dentro de la misma transacción [4:50].
No siempre quieres que todo se revierta. Si enviar un email falla, ¿debería eso impedir que el precio se actualice? Probablemente no, porque son procesos independientes.
Para estos casos, @Transactional ofrece dos parámetros clave:
java @Transactional(noRollbackFor = EmailAPIException.class) public void updatePrice(...) { // actualizar precio sendEmail(); }
Al repetir la prueba con esta configuración, sigues recibiendo el error 500 por el email fallido, pero el precio de la pizza sí cambia en la base de datos [6:15]. Justo el comportamiento que necesitas cuando una operación secundaria no debe bloquear la principal.
¿Cuál es la diferencia entre rollbackFor y noRollbackFor?
rollbackForindica qué excepciones deben revertir la transacción;noRollbackForindica cuáles deben permitir el commit aunque se lancen.
La propiedad propagation define cómo se comporta un método transaccional cuando ya existe (o no) una transacción activa.
El valor por defecto es Required: si hay una transacción en curso, el método se une a ella; si no la hay, Spring crea una nueva automáticamente.
Otro valor común es Mandatory: exige que ya exista una transacción para ejecutar el método. Si no hay ninguna, lanza una excepción en lugar de crearla.
¿Qué hace propagation = Required en Spring? Es el comportamiento por defecto: usa la transacción existente si la hay, o crea una nueva si no existe ninguna.
Existen más tipos de propagación (Supports, Never, Nested, entre otros) y vale la pena revisar la documentación oficial para entender cada caso de uso.
Usar @Transactional no es opcional cuando manejas operaciones críticas. Algunas recomendaciones que se desprenden de la clase:
@Transactional cualquier método que ejecute dos o más llamadas a la base de datos.noRollbackFor para excepciones de servicios externos (como envío de emails) que no deberían afectar la persistencia principal.rollbackFor cuando trabajes con excepciones checked que por defecto Spring no revierte.Required para la mayoría de los casos, Mandatory cuando exiges contexto transaccional previo.Con esto, tu proyecto Spring Data JPA queda más robusto y preparado para escalar. ¿Has tenido algún caso donde un rollback inesperado te haya causado problemas en producción? Cuéntame en los comentarios cómo lo resolviste.
++Spring Data JPA++
adjunto un link acerca de las propagación de las transacciones como para entender un poco más
Transaction Propagation and Isolation in Spring @Transactional
Hola, perdí dos horas sin comprender por qué no funcionaban los parámetros noRollbackFor y propagation de @Transactional sólo para darme cuenta que estaba usando import jakarta.transaction.Transactional; en lugar de import org.springframework.transaction.annotation.Transactional; para que caigan en lo mismo jaja

El @Transactional tambien se puede aplicar a toda la clase, no solo a uno de los metodos
Excelente anotacion pero me parece que viola el principio SOLID, no deberiamos crear funciones con mas de una responsabilidad. Me pueden corregir si estoy equivocado
No escuche que haya mencionado el profe, pero es importante saber que solo hace rollback a excepciones RuntimeException o que extienden de el, si es una excepcion de Exception, no hará rollback :D
Por si a alguien más le interesa las configuraciones de @Transactional:
Yo tengo una duda, el porque en la clase pasada marcaba un error por no tener esta anotación Transactional si solo hace una sola operación, no se debe poner en un método que haga dos o más operaciones en la base de datos?
Listo ✅
Hola tengo este codigo
while (attempt < maxAttempts && !stopCondition) { String ciudadAlmacen = engineConfigurationJdbc.getCiudadAlmacen(); String engine = engineConfigurationJdbc.getStepEngineName(); entityManager.getEntityManagerFactory().getCache().evictAll(); //List<LogEngineExecutionResponse> result = logEngineExecutionRepo.findLatestLogsByCityAndEngine(ciudadAlmacen,engine); List<LogEngineExecutionResponse> result = getLatestLogsByCityAndEngine(ciudadAlmacen,engine);
attempt++; try { Thread.sleep(queryIntervalInMillis); // Esperar antes de la siguiente consulta } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
y cada vez q hace el while el repository no me trae los registros mas nuevos, sino que siempre se cicla en los mismo. Debo usar trabsactional? se supone que ya limpie cache cada vez q termina el cilo del while