2014-12-31 14 views
6

La mia entità ha sia la chiave primaria (id) autogenerata che la chiave aziendale (spazio dei nomi). Devo aggiornare il record sostituendo quello vecchio. Quindi, lo sto cercando per chiave aziendale, cancellarlo e salvare una nuova entità. Funziona se ogni operazione nella propria transazione. Ma una volta che li ho messi tutti nella stessa transazione, quando viene eseguito il salvataggio di save(), delete() non è stato ancora eseguito, quindi ottengo una violazione del vincolo.Spring JpaRepository: delete() con successivo save() nella stessa transazione

transactionTemplate.execute(status -> { 
    MyEntity oldEntity = repository.findByNamespace(namespace); 
    if (oldEntity != null) { 
     repository.delete(oldEntity); 
    } 
    repository.save(newEntity); 
    return null; 
}); 

ho effettivamente riuscito a bypassare con l'aggiunta di

repository.flush(); 

Ma io davvero non capisco il motivo per cui ho bisogno di questa flush().

+1

Penso che sia perché il provider JPA si sente libero di riorganizzare e/o ottimizzare le scritture di database delle modifiche in sospeso dal contesto persistente, in particolare il provider JPA non si sente obbligato a eseguire le scritture del database nell'ordinazione e nel modulo implicato dai cambiamenti individuali del contesto persistente. Ad ogni modo, la situazione descritta è nota e il metodo flush() è noto. – Michal

risposta

4

Perché repository.flush() svuota le modifiche al database chiamando EntityManager.flush(). Quindi quando svuoti le modifiche dopo delete(), sql viene eseguito e il seguente salvataggio non avrà problemi.

Se non si chiama flush, è il provider di persistenza a determinare quando svuotare le modifiche con il tempo di commit della transazione. Inoltre, i fornitori non svuotano le modifiche in alcun ordine particolare, quindi può capitare che a volte l'operazione abbia esito positivo e talvolta no. Di solito, i fornitori di aspettare fino a quando il tempo a filo commit, ma si può influenzare che impostando una modalità di colore:

for entitymanager 
EntityManager.setFlushMode(FlushModeType type); 

or for query 
Query.setFlushMode(FlushModeType type); 

C'è un'impostazione equivalente nei dati primavera APP anche, ne sono sicuro, ma non lo faccio esattamente sapere qual è.

Si noti tuttavia che il lavaggio immediato delle modifiche riduce le prestazioni, pertanto è necessario prestare attenzione durante l'utilizzo. Nel tuo caso particolare è meglio aggiornare l'entità, quindi è necessario cancellarla e quindi mantenerne la nuova con la stessa chiave aziendale.

Problemi correlati