ScalaSQL: Interfaz sencilla para JDBC desde Scala

Desde hace tiempo que Groovy es mi lenguaje favorito para hacer scripts que a veces necesito para interactuar con bases de datos (algunos reportes o modificar ciertos datos, procesamiento por lotes, etc).

Son principalmente dos razones por las que me gusta tanto usar Groovy para este tipo de scripts:

  1. Tengo a mi disposición todo un arsenal de componentes de Java (simplemente con el JDK tengo un montón de cosas) y además todo lo que me ofrece Groovy como lenguaje, encima del JDK de Java (closures, comprehensión de listas, etc).
  2. El componente groovy.sql.Sql me permite interactuar con bases de datos de manera muy sencilla.

En Scala aún no hay un componente similar. Y aunque lo hubiera, no usaría Scala para scripting (ya he escrito al respecto anteriormente). Pero creo que sí hace falta. Si bien existe el hiperútil componente JdbcTemplate de Spring, para el cual además ya existen unas adiciones para Scala (junto con otras cosas de bean factories) en el proyecto ScalaPrimavera, no siempre es posible o deseable comenzar a depender de Spring.

Así que me propuse desarrollar un componente similar al Sql de Groovy, con algunas cosas adicionales que me han resultado muy útiles de JdbcTemplate, con la finalidad de usarlo en aplicaciones Scala, de modo que debe ser seguro su uso en ambientes multi-hilo, debe tener buen performance, debe manejar bien la transaccionalidad y sobre todo debe ser sencillo de usar.

Primero empecé imaginándome el uso:

//Crearlo con un DataSource para poder usarlo desde varios hilos
//con distintas conexiones
val sql = new ScalaSql(algunDataSource)
//Obtener un solo registro; siendo Scala, esto debería ser un Option
val row = sql.firstRow("SELECT * FROM usuario WHERE clave=?", clave)
//Obtener una lista de registros
val rows = sql.rows("SELECT * FROM usuario WHERE fecha_alta > ?", new Date)
//Pasamos un closure que recibe un renglón y se invoca con cada
//registro obtenido; el renglón debe ser un mapa inmutable
sql.eachRow("SELECT * FROM cuenta WHERE saldo > ?", saldo) { row =>
  //Hacer algo con el mapa
  //Si alguna columna tiene NULL en la base de datos, debemos tener None
  //Si conoces los nombres de columnas, no habrá problema en obtener los valores
  if (row("nombre") == None) { //no trae nombre
  } else { //si trae nombre
  }
  row("saldo") match {
    case s:BigDecimal => //Manejar BigDecimal de Scala, no Java
    case None => No viene saldo
  }
}
//Hacer operaciones dentro de una transaccion
sql.withTransaction { conn => //idealmente no necesitas nada con la conexion
  //Con esto obtenemos llaves autogeneradas
  val nuevaClave = sql.executeInsert("INSERT INTO usuario (nombre,saldo) VALUES (?, ?, ?)", row("nombre"), row("saldo"))
  //Dentro de la transaccion invocamos al mismo componente
  sql.executeUpdate("DELETE FROM usuario WHERE clave=?", row("clave"))
  //Si al final no hubo excepciones, se hace commit
}

En fin, esa es la idea. El código ya está disponible en GitHub y conforme lo utilice, iré agregándole funcionalidad. De entrada no me parece necesario que pueda ser creado o utilizado con una sola conexión, por diversas razones:

  • El esquema de una sola conexión es útil únicamente en scripts y programas de procesamiento por lotes (y a veces ni en esos casos).
  • Se complica bastante el código para poder soportar tanto DataSource como conexión simple en el mismo componente (hay que cerrar conexiones cuando es DataSource pero no cuando es una sola conexión, consideraciones adicionales para transaccionalidad, etc).
  • Para poder usar un solo componente desde varios hilos distintos, es necesario que cada hilo use su propia conexión, por lo tanto se necesita Datasource.

Como lo menciono en la página del proyecto, encontré algo similar ya existente, que incluso sospecho que también está inspirado en el Groovy SQL ya que sí tiene soporte para usarse con una conexión directamente (similar a cuando se crea el Groovy SQL con el puro URL, usuario, password y nombre de la clase del driver JDBC), pero no hay transaccionalidad ni obtención de llaves autogeneradas (aunque esto depende en última instancia de que el driver JDBC lo soporte realmente).

Pero bueno, pues ya hay una opción más para lidiar con bases de datos SQL desde Scala.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>