2010-12-08 26 views
2

obtenu le code comme ceci:Dans Grails, pourquoi est-ce que je reçois une StaleObjectStateException directement après l'actualisation? Je

def myObject = MyDomainClass.get(myId) 
myObject.refresh() 
myObject.myProperty = myValue 
myObject.save(flush:true, failOnError:true) 

En dépit de l'obtenir et le rafraîchissement, je suis parfois un « org.hibernate.StaleObjectStateException: ligne a été mis à jour ou supprimé par une autre transaction (ou mappage unsaved-value était incorrecte) "lorsque la sauvegarde est exécutée.

Cela se produit lorsque je commence à exécuter cette méthode simultanément dans plusieurs sessions. Mais alors la transaction 1 est définitivement terminé, ce code est exécuté à nouveau pour la transaction 2 et échoue encore! (J'utilise un service de transaction pour ré-exécuter des transactions lorsqu'elles échouent en raison d'un verrouillage optimiste, voir here).

Comment cela peut-il être bien que j'obtienne une version "fraîche" de la DB?

+0

Est-ce que 'MyDomainClass' h Avez-vous des relations en cascade, comme 'hasMany' ou' belongsTo'? Cela peut être les objets connectés qui sont mis à jour et enregistrés en cascade. À quelle classe fait référence StaleObjectStateException? –

+0

MyDomainClass possède des relations hasMany et belongsTo, mais l'exception se réfère directement à MyDomainClass # id. –

+0

@Joe, votre DomainClass a le champ de version? Et vous en avez besoin? – Gadonski

Répondre

1

This forum thread indique que vous pourriez avoir besoin d'une autre session Hibernate. Que faire si vous essayez une nouvelle session pour une nouvelle transaction, comme

Book.withNewSession{} 
+0

Juste essayé, cela me donne un org.springframework.orm.hibernate3.HibernateSystemException: Tentative illégale d'associer une collection avec deux sessions ouvertes; l'exception imbriquée est org.hibernate.HibernateException: tentative illégale d'associer une collection à deux sessions ouvertes –

+0

Je crois que cela signifie que la collection à laquelle elle fait référence devrait être relue aussi. –

+0

J'ai aussi essayé de fermer la session avant la withNewSession, ce qui provoque alors une boucle sans fin dans la requête ... très étrange. Peut-être que vous avez raison sur la collection, même si je ne sais même pas à quelle collection il se réfère. Tant que je vais aller pour ma solution de contournement méchant ;-). –

1

I au moins trouvé une solution de contournement - faire reculer une transaction vide:

myDomain.withTransaction { status -> 
    status.setRollbackOnly() 
} 
0

vous devez utiliser

MyDomainClass.lock(myId) 

au lieu de