¿Por qué @Transactional podría NO funcionar en este código?
@Service
public class ReportService {
public void generate() {
saveAll(); // call inside the same class
}
@Transactional
public void saveAll() { ... }
}Opciones
- Porque el método es público y debe ser privado
- Las transacciones usan un proxy; una llamada dentro de la clase se lo salta (Opción correcta)
- Porque
@Transactionalsolo funciona en interfaces - Porque el método no declara ningún parámetro
Respuesta
Porque Spring aplica las transacciones mediante un proxy, y una llamada desde otro método de la misma clase (self-invocation) se salta el proxy
Por qué
Spring no cambia tu clase. Envuelve el bean en un objeto proxy que inicia la transacción y hace commit alrededor de la llamada.
Cuando una clase externa llama a reportService.saveAll(), pasa por el proxy y funciona. Pero cuando generate() llama a saveAll() dentro del mismo objeto, es una llamada Java normal sobre this, así que se salta el proxy y no hay transacción.
El mismo problema ocurre con métodos private o final. Solución: mueve el método a otro bean, o pon @Transactional en el método que se llama desde fuera.
Recuerda
La self-invocation y los métodos privados se saltan el proxy de Spring.