Transacciones con Groovy SQL en una aplicación Grails
Hay veces que, por diversas restricciones, no se puede disfrutar de GORM en ciertas aplicaciones Grails. Afortunadamente, existe la alternativa de usar SQL a-la-Groovy:
import javax.sql.DataSource
import groovy.sql.Sql
class MyService {
boolean transactional = false
DataSource dataSource
def serviceMethod() {
sql.eachRow("select * from table") {
println it
}
}
}
Sin embargo, el problema viene al necesitar transacciones. Como no podemos utilizar DomainClass.withTransaction{ ... }, necesitamos manipular los límites de la transacción manualmente.
Por desgracia, Groovy no tiene un withTransaction o algo parecido, aunque mediante metaprogramación lo podemos añadir nosotros mismos. La solución que propongo tiene las siguientes cosas en cuenta:
- Hay que evitar que se cree una nueva conexión con cada llamada al execute(), cacheando la conexión.
- Precisamente en esta última funcionalidad hay un bug que hay que evitar.
- Asumimos que es necesario enviar parámetros distintos a queries distintas.
Vayamos a ello. En primer lugar, necesitamos añadir una closure a la clase groovy.sql.Sql. Podemos hacerlo en cualquier parte de nuestro código (siempre y cuando lo hagamos antes de la transacción), aunque el lugar más apropiado es BootStrap.groovy:
import groovy.sql.Sql
class BootStrap {
def init = { servletContext ->
Sql.metaClass.withTransaction = { Closure stmt ->
cacheConnection(){
connection.autoCommit = false
try {
stmt().each {
execute(it.query, it.params)
}
connection.commit()
} catch ( e) {
connection.rollback()
throw e
} finally {
connection.autoCommit = true
}
}
}
}
def destroy = {
}
}
Después, para invocarlo, desde un servicio por ejemplo:
def sql = new Sql(dataSource)
Connection connection = sql.createConnection();
try{
def sql2 = new Sql(connection);
sql2.withTransaction {
[
[query:"nsert into table values (?,?,?)", params:[p1, p2, p3]],
[query:"insert into table2 values (?,?,?)", params:[p4, p5, p6]]
]
}
}finally{
if(sql.dataSource){
connection.close();
}
}
Esta solución es la descrita en este hilo, con la diferencia de que se le pueden pasar parámetros a la query.
Hay un JIRA abierto pidiendo esta funcionalidad que, de hecho, supuestamente ya está presente en el código de Groovy, pero está pendiente de ser testeada. Lo que yo sí que os puedo confirmar es que esta solución sí funciona perfectamente
Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically to your feed reader.





Comments
Aún no hay comentarios.
Lo siento, los comentarios están cerrados.