La mia applicazione carica un elenco di entità che devono essere elaborate. Questo accade in una classe che utilizza uno schedulerDevo passare un'entità gestita a un metodo che richiede una nuova transazione?
@Component
class TaskScheduler {
@Autowired
private TaskRepository taskRepository;
@Autowired
private HandlingService handlingService;
@Scheduled(fixedRate = 15000)
@Transactional
public void triggerTransactionStatusChangeHandling() {
taskRepository.findByStatus(Status.OPEN).stream()
.forEach(handlingService::handle);
}
}
Nei miei HandlingService
processi ogni attività nel issolation usando REQUIRES_NEW
per il livello di propagazione.
@Component
class HandlingService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handle(Task task) {
try {
processTask(task); // here the actual processing would take place
task.setStatus(Status.PROCCESED);
} catch (RuntimeException e) {
task.setStatus(Status.ERROR);
}
}
}
Il codice funziona solo perché ho iniziato la transazione padre sul TaskScheduler
classe. Se rimuovo l'annotazione @Transactional
le entità non sono più gestite e l'aggiornamento all'entità dell'attività non viene propagato al db.Non trovo naturale rendere transazionale il metodo pianificato.
Da quello che vedo ho due opzioni:
1. Mantenere il codice come lo è oggi.
- Forse è solo io e questo è un corretto approccio.
- Questa variante ha il minor numero di viaggi nel database.
2. Rimuovere il @Transactional
annotazione dal Scheduler, passare l'ID del compito e ricaricare l'entità compito nel HandlingService.
@Component
class HandlingService {
@Autowired
private TaskRepository taskRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handle(Long taskId) {
Task task = taskRepository.findOne(taskId);
try {
processTask(task); // here the actual processing would take place
task.setStatus(Status.PROCCESED);
} catch (RuntimeException e) {
task.setStatus(Status.ERROR);
}
}
}
- ha più viaggi al database (una query extra/elemento)
- può essere eseguito utilizzando
@Async
Per favore, puoi offrire la tua opinione su quale sia il modo corretto di affrontare questo tipo di problemi, magari con un altro metodo di cui non ero a conoscenza?
In questo esempio, la cache delle entità di sessione della transazione nidificata verrà sincronizzata con la sessione della transazione esterna? Ad esempio, se l'entità "Attività" viene modificata all'interno della transazione nidificata, tale modifica verrà applicata anche alla sessione della transazione in uscita? – froi
Seguito alla mia domanda, poiché la sessione della transazione esterna viene svuotata, significa che le modifiche all'attività verranno considerate come modifiche "obsolete"? – froi