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
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? –