L'entità di ibernazione che sto salvando nel database (Oracle) ha relazioni molto complesse, nel senso che ha molte entità correlate. Sembra qualcosa di simile ...StaleStateException durante il salvataggio di entità con relazioni complesse
@Table(name = "t_HOP_CommonContract")
public class Contract {
@Id
private ContractPK id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private ContractGroupMember contractGroupMember;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "TransactionId", referencedColumnName = "TransactionId"),
@JoinColumn(name = "PrimaryContractId", referencedColumnName = "PrimaryContractId")
})
@Fetch(FetchMode.SUBSELECT)
private List<ContractLink> contractLinks;
// . . . . . . .
// A couple of more one to many relationships
// Entity getters etc.
}
Ho anche un altro paio di entità come ...
@Table(name = "t_HOP_TRS")
public class TotalReturnSwap {
@Id
private ContractPK id;
// Entity Getters etc.
}
Il trucco è che devo fare la persistenza di Contract
e TotalReturnSwap
entità la stessa transazione.
A volte potrebbe essere un gruppo di entità che devono essere mantenute nella stessa transazione.
Ho notato la seguente eccezione quando salvo l'entità TotalReturnSwap
(che viene sempre eseguita dopo aver salvato l'entità Contract
).
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:675) \
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.performTDWPersistenceForContracts(DownstreamContractBusinessEventPostingService.java:102)
at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.persistContractBusinessEvent(DownstreamContractBusinessEventPostingService.java:87)
at com.rbs.fcg.publishing.DownstreamContractBusinessEventPostingService.publish(DownstreamContractBusinessEventPostingService.java:67)
at com.rbs.fcg.publishing.PublishingProcessor.publish(PublishingProcessor.java:76)
at com.rbs.fcg.publishing.PublishingProcessor.process(PublishingProcessor.java:52)
at com.rbs.are.MultiThreadedQueueItemProcessor$2.run(MultiThreadedQueueItemProcessor.java:106)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
Ora un paio di punti che possono aiutare, mentre rispondendo alle domande:
- sto solo salvando (inserimento) entità in database - mai l'aggiornamento/cancellazione/leggendo
- sono stato in grado di isolare questa eccezione anche in ambienti a thread singolo, quindi non sembra un problema di multi-threading, anche se la nostra applicazione è multi-thread
A proposito di # 5, come possiamo risolverlo? – Stony
@Stony Forse un 'Refresh()'? – Michael
@Michael Il mio problema è che 2 thread modificano lo stesso PO allo stesso tempo; quindi, quando salva il PO, come motivo # 5, lancia un'eccezione. quindi quando chiami l'aggiornamento() nel caso? Se before save(), la modifica per l'ordine PO sarà scomparsa. Infine, ho usato il lock LockMode.PESSIMISTIC_WRITE per risolvere il mio problema. Qualcuno ha una soluzione migliore? – Stony