2010-11-07 53 views
1

我有一个Grails应用程序,用户通过Spring Security登录。然后他们的用户域在登录期间被加载到会话中。Grails:乐观锁定,StaleObjectStateException与Spring安全会话,更新计数器

当另一个用户执行更新数据库中的用户对象上的计数器的动作时,我得到一个StaleObjectStateException user.save(flush:true)当前正在另一个登录用户

Eg我在会话中拥有“用户A”对象,以便登录用户A. 然后,当用户B登录并执行更新用户A对象的操作,但版本不同步。

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) 

我试过合并但没有运气。

因为有用户域这么多的更新,数以百计的用户将可以登录了。但我不知道什么影响,这将有一致性我想的完全取出“版本”属性的数据随着时间的推移。

将交换user.save(flush:true)User.executeUpdate(Update viewCount where ...)解决问题,并带来更多的缓存问题?

或者,我可以选择在更新时他们可以忽略“版本”的具体性质。 虽然在这个例子中,我并不完全明白发生了什么。 http://grails.1312388.n4.nabble.com/GORM-setting-access-field-td1592837.html

所以,我怎么能解决这个问题?

回答

1

解决:基本上没有对会话的用户域。只是用户ID。因此,您可以在需要使用域时加载域。

的解决方案是不使用会话内的域对象。使用id代替,然后为每个需要用户数据的请求加载对象。这是Grails的Spring安全插件中引入的差异。欲了解更多信息看看这里(官方文档):

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

+0

能告诉你如何加载每个请求的对象使用的会话的域对象避免的例子吗? – Alison 2012-12-25 00:00:48

+0

当你为第一个请求加载一个对象时,那么在这之后的会话中不是吗?然后你可以放弃/驱逐,但我无法弄清楚如何在这之后重新获得它。 – Alison 2012-12-25 00:12:34