2010-06-05 13 views
12

He estado actualizando todos mis servicios para que sean transaccionales mediante el uso de la capacidad de Grail de retrotraer cuando se lanza una RuntimeException en el servicio. He, en la mayoría de los casos, hacer esto:Recuperación de una transacción en un servicio de Grails

def domain = new Domain(field: field) 
if (!domain.save()) { 
    throw new RuntimeException() 
} 

De todas formas, quería comprobar que este hecho va a deshacer la transacción ... me hizo pensar acerca de si en este punto ya se ha comprometido también .. , si no, se pondría al ras: ¿cambiar eso? No estoy muy familiarizado con cómo Spring/Hibernate hace todo esto :)

Respuesta

15

Sí, eso lo hará.

Las transacciones en Grails se manejan de forma predeterminada en un nivel de método de servicio. Si el método retorna normalmente, se comprometerá la transacción; si se lanza una RuntimeException, la transacción se retrotraerá.

Tenga en cuenta que incluso si usa flush: true mientras se guarda un objeto en el método del servidor, los cambios de db se revertirán si lanza una RuntimeException.

Por ejemplo:

class MyService { 

def fiddle(id,id2){ 
    def domain = Domain.findById(id) 

    domain.stuff = "A change" 
    domain.save(flush:true) // will cause hibernate to perform the update statements 

    def otherDomain = OtherDomain.findById(id2)  

    otherDomain.name = "Fiddled" 

    if(!otherDomain.save(flush:true)){ // will also write to the db 
    // the transaction will be roled back 
    throw new RuntimeException("Panic what the hell happened") 
    }               
} 
} 

lo que no estoy 100% claro con Grails es lo que sucede si una excepción comprobada es lanzada en Java recta/mundo de primavera es el comportamiento por defecto para la transacción de cometer inceptor la transacción, a través de esto, puede ser anulada en la configuración.

Nota: hay una advertencia, y es que su base de datos tiene que admitir transacciones en las tablas que está actualizando. Sí, esto es poke en MySQL :)

Esto también se aplica al método Domain.withTransaction.

+0

Impresionante, gracias! – RyanLynch

+0

contento de estar de servicio –

+0

Las excepciones personalizadas que extienden RuntimeException deberían estar bien, ¿verdad? Además, puede habilitar transacciones en MySQL estableciendo: dialect = org.hibernate.dialect.MySQLInnoDBDialect en dataSource :) – RyanLynch

2

Solo quería agregar comentarios adicionales a la respuesta aceptada, y esto fue demasiado largo para caber en un comentario.

lo que no estoy 100% claro con Grails es lo que sucede si una excepción comprobada se lanza

Por defecto, la excepción no se debe comprobar, o la transacción no se pondrá en marcha espalda. Aparentemente eso es algo de primavera.

Si realmente desea verificar las excepciones en un método, puede marcar explícitamente el método de servicio como @Transactional y usar el argumento rollbackFor para enumerar qué excepciones aún deben causar una reversión. (Tenga en cuenta que en realidad no lo he probado).

Tenga en cuenta, sin embargo, que marcar cualquier método en un servicio con @Transactional deshabilita el ajuste automático de sus otros métodos con una transacción. Entonces, si lo haces por uno, tienes que hacerlo por todos. Asegúrese de que realmente necesidad de declarar dichas excepciones comprobadas;)

Usted puede leer más sobre esto en http://docs.grails.org/latest/guide/services.html.

Cuestiones relacionadas