Credo che abbiamo bisogno di distinguere tra 'logico' operazione ambiti e le transazioni 'fisici' qui ...
Cosa PROPAGATION_REQUIRED crea è un ambito di transazione logico per ogni metodo a cui viene applicato. Ciascun ambito di transazione logica può decidere individualmente nello stato di rollback solo con lo stato della transazione esterna che è logicamente indipendente da l'ambito della transazione interna. Del corso , in caso di comportamento standard PROPAGATION_REQUIRED, essi verranno associati alla stessa transazione fisica . Quindi un indicatore di rollback solo impostato nello scope della transazione interna influisce sulla possibilità della transazione esterna di eseguire effettivamente il commit.Tuttavia, dal momento che l'ambito di transazione esterno non decidere su un rollback per sé, il rollback (in silenzio innescata dalla portata transazione interna) viene fornito inaspettato a quel livello - che è il motivo per cui un UnexpectedRollbackException si butta.
PROPAGATION_REQUIRES_NEW, al contrario, utilizza un transazione completamente indipendente per ciascun interessato ambito di transazione. In tal caso, le transazioni fisiche di base saranno diverse e potranno quindi eseguire il commit o il rollback in modo indipendente, con una transazione esterna non influenzata dallo stato di rollback della transazione interna .
PROPAGATION_NESTED è ancora diversa dal fatto di utilizzare una singola transazione fisica con più punti di salvataggio che possa ripristinare. Tali parziali rollbacks permettono un interno transazione scopo di innescare un ripristino per la sua portata, con la transazione esterno poter continuare la transazione fisica nonostante alcune operazioni essendo stato rotolato. Questo è tipicamente mappato sui punti di salvataggio JDBC, , quindi funzionerà solo con le transazioni J2BC transazioni (Spring's DataSourceTransactionManager).
Per completare la discussione: UnexpectedRollbackException può anche essere gettato senza l'applicazione mai aver impostato un rollback-unico marcatore sé. Invece, l'infrastruttura della transazione potrebbe aver deciso che l'unico risultato possibile è un rollback , a causa di vincoli nello stato corrente della transazione . Questo è particolarmente rilevante con le transazioni XA .
come ho suggerito sopra, un'eccezione al interno di transazione ambito, quindi la cattura di tale eccezione al l'ambito esterno e tradurlo in una chiamata in setRollbackOnly silenziosa ci dovrebbe funzionare per lo scenario. Un chiamante della transazione esterna non visualizzerà mai un'eccezione, quindi . Dal momento che si solo preoccuparsi di tali ripristini silenziosi a causa dei requisiti speciali imposti da un chiamante, vorrei anche sostengo che la corretta soluzione architettonica è quella di utilizzare le eccezioni all'interno il livello di servizio, e per tradurre tali eccezioni in rollback silenziosi al livello della facciata del servizio (a destra prima di tornare al chiamante speciale ).
Dal momento che il problema non è forse solo sulle eccezioni di rollback, ma piuttosto su eventuali eccezioni generate dal vostro livello di servizio, si potrebbe anche uso standard di eccezione-driven rollback tutta la strada in tutta si livello di servizio, e poi prendere e registrare tali eccezioni una volta che la transazione ha già completato, in qualche facciata servizio adattamento che traduce eccezioni del livello di servizio in specifici UI errore stati.
Juergen
Quel particolare viene generata un'eccezione solo in determinate circostanze specifiche, da dentro l'infrastruttura Spring TX. Quale messaggio era contenuto all'interno di 'UnexpectedRollbackException'? Questo ci aiuterà a rintracciarlo. – skaffman