La entidad de hibernación que guardo en la base de datos (Oracle) tiene relaciones muy complejas, en el sentido de que tiene muchas entidades relacionadas. Se ve algo como esto ...StaleStateException al guardar entidad con relaciones complejas
@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.
}
también tengo un par de más entidades tales como ...
@Table(name = "t_HOP_TRS")
public class TotalReturnSwap {
@Id
private ContractPK id;
// Entity Getters etc.
}
El truco es que tengo que hacer persistencia de Contract
y entidades en TotalReturnSwap
la misma transacción.
A veces podría ser un grupo de entidades que deben persistir en la misma transacción.
He notado la siguiente excepción cuando guardo la entidad TotalReturnSwap
(que siempre se hace después de haber guardado la entidad 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)
Ahora algunos puntos que pueden ayudar al responder preguntas:
- Yo sólo estoy ahorrando (insertar) las entidades de base de datos - no actualizar/borrar/leyendo
- he podido aislar esta excepción incluso en entornos de un solo subproceso, por lo que no parece un problema de subprocesos múltiples, aunque nuestra aplicación es multiproceso
sobre # 5, ¿cómo podemos resolverlo? – Stony
@Stony ¿Quizás un 'Refresh()'? – Michael
@Michael Mi problema es que 2 hilos modifican el mismo pedido al mismo tiempo; entonces cuando guarde el PO, como el motivo # 5, haga una excepción. Entonces, ¿cuándo llamar a la actualización() en caso? Si antes de guardar(), el cambio para el PO simplemente se habrá ido. Finalmente, utilicé el bloqueo LockMode.PESSIMISTIC_WRITE para resolver mi problema. Alguien tiene una mejor solución? – Stony