martes, 28 de febrero de 2012

Orden y formato al código PL/pgSQL


“Any code of your own that you haven’t looked at for six or more months might as well have been written by someone else.”
Eagleson’s Law

Leer y entender un trozo de código de unas pocas líneas es fácil, aunque haya sido escrito como si se hubiese caído al suelo y esparcido por toda la habitación. Ahora bien, si tenemos que leer unos cuantos cientos o miles de líneas, la cosa cambia bastante. Es fundamental tener un código ordenado y bien identado para facilitar la legibilidad.

Existen muchas herramientas que facilitan o realizan directamente esta tarea. Son las llamadas herramientas de embellecimiento o formato ("code beautifiers/formatters tools"). La mayoría de los IDE's y editores tienen herramientas para una gran variedad de lenguajes... salvo para PL, donde me he encontrado bastantes carencias.

Si necésitáis una herramienta de este estilo, una de las mejores que me he encontrado es Pl/Sql tidy. Algunas de sus características son:
  • Identación por bloques
  • Compactación
  • Ajuste de mayúsculas/minusculas
  • Alineamiento vertical en asignaciones
El uso de la herramienta es a través de línea de comando, pero también podéis usar la interesante versión online disponible.

Funciona con PL/pgSQL.


Referencias y más información:

miércoles, 1 de febrero de 2012

Apache Commons DbUtils: sencillo, rápido, ligero


“Controlling complexity is the essence of computer programming”
Brian Kernigan

Hoy traigo aqui otra de las joyas de Apache Commons: DbUtils. Ya comenté en el artículo anterior "Librerías imprescindibles en Java" que, en cualquier projecto, antes de pensar en hacer nuestras utilities, debemos pasar por la página de Commons para ver las librerías existentes antes de ponernos a reinventar la rueda. Pues bien, Commons tiene otra pequeña joya que he descubierto y aplicado recientemente con éxito.

Hay ocasiones en las que no usamos un framework de mapeo tipo ORM (JPA/EclipseLink, Hibernate, Mybatis -antiguo iBATIS-) por varias razones: modelo muy cambiante, proyecto muy pequeño, necesitamos un control más fino de las consultas, generación dinámica, etc... En estos casos, no nos queda más remedio que usar directamente JDBC. Sin embargo JDBC es un API muy engorroso que requiere mucho código de limpieza de recursos y mucha fontanería a través de sus capas. Más del 80% de nuestro código JDBC es la instanciación de objetos del API, establecimiento de parámetros, liberación y cierre.


DbUtils es un pequeño conjunto de clases diseñadas para hacer mucho más fácil el trabajo que hacemos con JDBC centrándonos en lo que queremos: consultar, actualizar, insertar. Especialmente nos ayuda en:
  • Se encarga automáticamente de la fontanería previa (conexión y preparación) y de la limpieza, evitando posibles errores de liberación de recursos.
  • Rellena las propiedades de JavaBean automáticamente a partir de ResultSets. No es necesario copiar manualmente valores en instancias de beans.
Por todo la anterior, el uso de DbUtils reduce drásticamente la cantidad de código que necesitamos con JDBC. Por hacer una comparativa, yo díría que DbUtils es a JDBC lo que JDOM a javax.xml.

Usar DbUtils es muy sencillo. Hay dos clases/interfaces principales que constituyen el corazón de DbUtils: QueryRunner y ResultSetHandler. QueryRunner se encarga de realizar todo el trabajo: abre la conexión, ejecuta la consulta o actualización y devuelve el resultado. Para devolver el resultado de diferentes formas se usan las distintas implementaciones de la clase ResultSetHandler, que permite devolver el resultado en una lista de  POJO's, lista de arrays, lista de Map, etc...

A continuación pongo un ejemplo simple de una pequeña DAO de una aplicación que tuviese que acceder a una base de datos PostgreSQL y a un AS/400 simultáneamente. En el ejemplo se pueden observar características muy importantes de ahorro de código y, por tanto, de su consecuencia más valiosa, ahorro de tiempo:
  • No hay declaraciones de Connection, Statement y ResultSet.
  • No hay liberación de recursos (DbUtil lo hace automáticamente)
  • No es necesaria la engorrosa recolección de campos a través de la iteración del ResultSet. Podemos devolver las consultas en un Map<String, Object> (NombreCampo, Valor) o en un JavaBean cuyas propiedades coincidan con los campos que devuelva nuestra consulta.


/**
   Suponemos una clase DAO cualquiera de acceso a datos
*/
public class ASDao {
   
   private AS400JDBCDataSource asDataSource;
   private PGSimpleDataSource pgDataSource;
   private QueryRunner qr;

   public ASDao() throws Exception {
       // El datasource puede instanciarse...
       asDataSource = new AS400JDBCDataSource("host4.cestel.es","asuser","xxxxxx");
       // U obtenerse a partir de un JNDI de un contenedor
       pgDataSource = new InitialContext().lookup("java:comp/env/jdbc/pgDS");
       qr = new QueryRunner(asDataSource);
       qrp = new QueryRunner(pgDataSource);
   }


   /**
       Realiza una consulta parametrizada (que debe devolver una sóla fila) y 
       devuelve un Map<String,Object> con el nombre del campo
       y su valor. Se asume que la consulta devuelve una sóla fila.
       Son apenas dos líneas.
   */
   public Map<String,Object> findData(String clientCode, String debtCode) 
                                                                throws SQLException {
       MapHandler result = new MapHandler();
       return qrp.query(
               "select c.id, c.code, de.id, de.customer_debt_id, dos.id, dos.code\n" +
               "from debt de join dossier dos on de.dossier_id = dos.id \n" + 
               "join customer c on dos.customer_id = c.id\n" +
               "where customer_debt_id = ?\n" +
               "and c.code=?\n" +
               "and end_process_date is null", result,debtCode, clientCode);
   }

   /**
       Realiza una consulta parametrizada y devuelve el resultado como una lista de 
       JavaBeans "TablaAS". La creación de la lista y "llenado" de los objetos corre 
       por su cuenta. Lo único que tenemos que hacer es crear la clase TablaAS con 
       propiedades (getter, setter). Las propiedades de los POJO (JavaBeans) que 
       se "llenaran" serán aquellas cuyo nombre coincida con el campo devuelto.
       Dos líneas (más la clase)
   */
   public List<TablaAS> findByClient(String clientCode) throws SQLException {
       ResultSetHandler<list<TablaAS>> blh = new BeanListHandler<TablaAS>(TablaAS.class);
       return qr.query("select * from  CESQ.TABLA_AS where CODCLTE = ?", blh,clientCode);
   }

   /**
       Ejemplo de la misma consulta devuelto como un array 
       o como una lista de POJO's (JavaBean)
   */
   public void test() throws SQLException {
       ArrayHandler ah = new ArrayHandler();
       ResultSetHandler<list<TablaAS>> h = 
                       new BeanListHandler<TablaAS>(TablaAS.class);
       
       Object[] resultArray = 
           qr.query("select * from  CESQ.TABLA_AS FETCH FIRST 2 ROWS ONLY", ah);

       List<TablaAS> result = 
           qr.query("select * from  CESQ.TABLA_AS FETCH FIRST 2 ROWS ONLY", h);

   }
}

Como todas las cosas, obviamente DbUtils tiene un target concreto de aplicación, no es una bala de plata para todo. Ahora bien, si no devolvemos conjuntos de datos grandes, podría usarse como perfecto sustituto de JDBC con un mínimo impacto en el rendimiento y con una importante mejora en legibilidad y mantenibilidad.

Puedes ver más ejemplos en el sitio de DbUtils.


Referencias y más información:
Related Posts Plugin for WordPress, Blogger...
cookieassistant.com