2010-11-07 15 views
1

J'ai une application Grails où les gens se connectent via Spring Security. Leur domaine utilisateur est ensuite chargé sur la session pendant la durée de la connexion.Grails: verrouillage optimiste, StaleObjectStateException avec domaine sur la session avec Spring Security, mise à jour des compteurs

Je reçois une exception StaleObjectStateException lorsqu'un autre utilisateur exécute une action qui met à jour un compteur sur un objet utilisateur dans la base de données user.save(flush:true) actuellement sur une autre session d'un utilisateur connecté

Par exemple J'ai l'objet "Utilisateur A" sur la session pour l'utilisateur connecté A. Ensuite, quand un utilisateur B est connecté, et préforme une action pour mettre à jour l'objet Utilisateur A, mais la version est désynchronisée.

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.example.User#2] 

     at $Proxy12.merge(Unknown Source) 

J'ai essayé de fusionner mais pas de chance.

Je pense à supprimer complètement la propriété "version" car il y a tellement de mises à jour sur le domaine utilisateur que des centaines d'utilisateurs seraient connectés. Mais je ne sais pas quel effet cela aurait sur la cohérence des données au fil du temps.

Le remplacement user.save(flush:true) par User.executeUpdate(Update viewCount where ...) résoudrait-il le problème et entraînerait plus de problèmes de mise en cache?

Ou est-ce que je peux sélectionner des propriétés spécifiques qui peuvent ignorer "version" lors de la mise à jour. Je ne comprends pas vraiment ce qui se passe avec cet exemple. http://grails.1312388.n4.nabble.com/GORM-setting-access-field-td1592837.html

Alors, comment puis-je résoudre ce problème?

Répondre

1

Résolu: Fondamentalement, n'ont pas le domaine de l'utilisateur sur la session. Juste l'identifiant des utilisateurs. Ainsi, vous pouvez charger le domaine lorsque vous avez besoin de l'utiliser.

La solution est de ne pas utiliser un objet de domaine dans la session. Utilisez plutôt l'ID, puis chargez l'objet pour chaque requête nécessitant les données utilisateur. C'est les différences introduites dans le plugin de sécurité de printemps pour les grails. Pour plus d'informations consulter ici (documentation officielle):

http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/guide/2%20Differences%20Between%20the%20Spring%20Security%20and%20Acegi%20Plugins.html

+0

Pourriez-vous montrer un exemple de la façon dont le chargement de l'objet pour chaque requête en utilisant l'objet évite de domaine dans la session? – Alison

+0

Lorsque vous chargez un objet pour la première requête, n'est-ce pas dans la session après cela? Vous pouvez ensuite défausser/expulser, mais je n'arrive pas à comprendre comment le récupérer après cela. – Alison