2009-01-28 17 views
7

Escribo una aplicación pequeña de Grails, y sigo recibiendo StaleObjectStateException: s para aproximadamente 1/10: th de las llamadas a "createfoo" cuando ejecuto el siguiente código bastante simple. Probablemente me esté perdiendo la mejor manera de usar GORM.GORM en Grails y StaleObjectStateException

Este es el código:

def viewfoo = { 
    session.user.refresh() 
    // ... 
} 

def createfoo = { 
    session.user.refresh() 
    var user = session.user 
    if (param["name"]) { 
    var newFoo = new Foo() 
    newFoo.name = param["name"] 
    if (newFoo.validate()) { 
     newFoo.save() 
     if (user.validate()) { 
     user.addToFoos(newFoo) 
     } else { 
     user.discard() 
     } 
    } else { 
     newFoo.discard() 
    } 
    } 
} 

Mis preguntas con respecto GORM mejores prácticas:

  1. es el "validar si-() - entonces-save() - otro descarte() "la forma correcta de persistir un nuevo objeto en GORM?

  2. ¿Debo validar todos los objetos que voy a guardar()? Es decir. ¿Debería validar tanto el Foo-object como el User-object en el código anterior? ¿Validará el objeto de usuario implícitamente comprobar el estado del Foo-objeto?

  3. ¿Qué hice para merecer StaleObjectStateException? :-)

La excepción GORM/Hibernate:

 
Caused by: Object of class [Foo] with identifier [15]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Foo#15] 

Respuesta

2

No estoy muy seguro de por qué estás teniendo problemas, pero hay un método merge en objetos de dominio. Le permite volver a conectar el objeto actual al contexto persistente actual.

No sé lo suficiente acerca de lo que su Foo, o las personalizaciones que le ha hecho al objeto Usuario, o la versión de grails/java que está utilizando para poder reproducir esto.

Estoy pensando que tiene algo que ver con la actualización que está haciendo en el objeto de usuario que está causando que la versión de la base de datos se actualice (y por lo tanto se desincronice), pero no estoy seguro.

Además, creo que la confirme, luego descartar el comportamiento está cambiando y menos necesaria en griales 1.1 Basándose en los comentarios de this post

2

Una cosa que noto es que usted no está ahorrando usuario, a pesar de que acaba de añadir un poco de foo a ella. De hecho, salvar al usuario debería evitar la necesidad de guardar foo.

No tiene que validar usuario: las fuentes que no son de confianza cambian sus propiedades, y las restricciones de nivel de base de datos se verifican de todos modos cada vez que se guarda.

Por último, cosas como user.refresh() se mueven mejor fuera de tus acciones y en un interceptor o un filtro.