记录上次登录grails时乐观锁定失败

记录上次登录grails时乐观锁定失败,grails,spring-security,Grails,Spring Security,从Grails1.3开始,我用这段代码记录“上次登录”已经有一段时间了。现在在Grails2.2.4中,“乐观锁定失败”让我很恼火。我认为只有在重新启动应用程序时才会发生这种情况。我想知道如何更好地进行,避免“乐观锁定错误”。涉及到spring安全和spring安全ui class InteractiveAuthenticationSuccessEventListener implements ApplicationListener<InteractiveAuthenticationSuc

从Grails1.3开始,我用这段代码记录“上次登录”已经有一段时间了。现在在Grails2.2.4中,“乐观锁定失败”让我很恼火。我认为只有在重新启动应用程序时才会发生这种情况。我想知道如何更好地进行,避免“乐观锁定错误”。涉及到spring安全和spring安全ui

class InteractiveAuthenticationSuccessEventListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
    private static final Logger LOG = Logger.getLogger('au.com.interlated.emissionscalculator.InteractiveAuthenticationSuccessEventListener')

    void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {

    ResPerson person
    try {
        ResPerson.withTransaction {
            person = ResPerson.findById(event.authentication.principal.id)
            if (!person.isDirty()) {
                if (!person.isAttached())
                    person.attach()


                person.lastLoggedIn = new Date()

                // doesn't save it is not the end of the world. Wondering if multiple requests at a time can cause this.
                try {
                    person.merge(flush: true)
我已尝试捕获一系列异常:

    } catch (e) {
        LOG.error "Failed to save login record : ${e.message}"
    } catch (OptimisticLockingFailureException olfe) {
        LOG.error "Failed to save login record. Optimistic Locking Failure."
    } catch (org.hibernate.StaleObjectStateException sose) {
        LOG.error "Failed to save login record (stale object) ${sose.message}"
    }

要么避免问题,要么至少抓住它就好了。

使用
lock
而不是
findById
。这样,您就可以独占访问更新,并可以避免乐观锁定问题。另外,不需要
isDirty
和附加检查,这些检查更多用于会话中有断开连接的实例(这通常是个坏主意),但从数据库加载实例的情况。因此,这应该是可行的:

ResPerson.withTransaction {
   ResPerson person = ResPerson.lock(event.authentication.principal.id)
   person.lastLoggedIn = new Date()
   person.save()
}

使用
lock
而不是
findById
。这样,您就可以独占访问更新,并可以避免乐观锁定问题。另外,不需要
isDirty
和附加检查,这些检查更多用于会话中有断开连接的实例(这通常是个坏主意),但从数据库加载实例的情况。因此,这应该是可行的:

ResPerson.withTransaction {
   ResPerson person = ResPerson.lock(event.authentication.principal.id)
   person.lastLoggedIn = new Date()
   person.save()
}