2011-12-02 22 views
8

Estoy trabajando con una aplicación web de Grails y obtengo muchas cosas extrañas cuando uso el servicio de Grails. Así que quiero hacer algunas preguntas sobre esto para que entienda más acerca de los servicios de Grails. Esto será muy útil para mí (y tal vez para otros^_ ^). Gracias por adelantado.Algunas preguntas sobre el servicio de Grails

  1. Si un servicio se configura con transaccional estática = true, tendrá que eliminar todos los datos de los cambios en DB después de invocar cualquier método con un objeto que está sucio y estar encerrado en sesión de Hibernate?

  2. ¿Puedo utilizar la anotación @Transactional en el nivel de clase en lugar de static transactional = true? ¿Y es posible poner @Transactional(readOnly = true) en algunos métodos que solo quiero que lean (consulten, encuentren) datos de DB?

  3. ¿Qué hay de la herencia de transacción? Quiero decir que, si el servicio principal está configurado static transactional = true, y el servicio hijo tiene su propia anotación @Transactional (en clase) y algo de @Transactional(readOnly = true) (en algunos métodos), ¿qué sucederá si invoco un método en el elemento primario del secundario?

  4. ¿Funciona la transacción con un servicio abstracto? Porque, como sé, con el servicio abstracto no podemos inicializar su bean, y quizás al iniciar la aplicación, hay algunas diferencias en el contexto de Grails.

Respuesta

7

Usted debe hacer una pregunta por pregunta :)

Para la pregunta # 1, sí - la primavera/Hibernate integración asegura que un rubor ocurre antes de la confirmación. Por lo tanto, las llamadas a save() y delete() se purgarán y no es necesario agregar flush: true a ninguna. Además, las instancias sucias a las que no haya llamado save() también se limpiarán a menos que llame al discard().

Para # 2: los servicios son transaccionales por defecto, por lo que transactional = true es realmente redundante; solo necesita especificarlo para decir transactional = false. Pero el contenedor automático de transacciones que se crea solo se realiza si no hay anotaciones @Transactional. Si tiene una o más anotaciones, entonces esas definen la demarcación de la transacción. Por lo tanto, de manera predeterminada (es decir, sin anotaciones ni la propiedad transactional ni transactional = true), todos los métodos son transaccionales, pero si solo se anota un subconjunto de los métodos, solo aquellos serán transaccionales.

Normalmente utilizaría anotaciones cuando desee un comportamiento no predeterminado, es decir, propagación personalizada, aislamiento, tiempo de espera, etc. (o haga que sea de solo lectura como en su ejemplo).

Puede anotar en el nivel de clase para tener la misma configuración para todos los métodos, y opcionalmente anotar métodos individuales para anular los valores predeterminados de clase-alcance.

Para # 3 y # 4, se aplican las reglas estándar (ver # 2). Si la subclase tiene anotaciones, se ignorará transactional = true de esa clase o una clase principal, ya que al usar las anotaciones, le dice a Grails que usted mismo está configurando las cosas.

Dado que los servicios abstractos no pueden crearse instancias, la subclase concreta que está realmente instanciada tendrá un comportamiento combinado de la clase base y de sí mismo. Si todo es transactional = true, entonces es simple, y si tiene anotaciones, entonces definen las reglas.

Los métodos de llamada en la superclase se comportarían igual que los métodos de llamada en la clase actual. Pero el comportamiento es un poco contra-intuitivo si no has considerado las implicaciones del enfoque de proxy de Spring. Cuando llama a un método transaccional, el proxy intercepta la llamada y se une a la transacción activa, o inicia una nueva si es necesario, o inicia una nueva si se especifica REQUIRES_NEW. Pero una vez que esté en la clase real y llame a otro método, omitirá el proxy. Entonces, si llamas a otro método con diferentes configuraciones de anotación, serán ignoradas. Si va a hacer eso, consulte esta discusión de la lista de correo para saber qué ocurre y cómo trabajar con él: http://grails.1312388.n4.nabble.com/non-transactional-service-extends-transactional-service-outcome-td3619420.html

+0

Awesome! Muchas gracias por sus respuestas claras. Pero echemos un vistazo al punto n. ° 3 con el reverso: el servicio principal A está marcado como @Anotación a nivel de clase y el método doParent() en A es readOnly = true, mientras que el servicio secundario B no tiene ninguna configuración específica sobre la transacción. ¿Por qué llamo a doParent() desde B, aún así vacia datos aunque lo obligo a leer solo? –

Cuestiones relacionadas