Migrando la lista de ventas a Hibernate en nuestra aplicación PrimeFaces/JSF/Spring/Hibernate

Migrando la lista de ventas a Hibernate en nuestra aplicación PrimeFaces/JSF/Spring/Hibernate magm 9 Abril, 2013 - 18:59

Hola gente,


seguimos con nuestra aplicación, en esta ocasión migraremos la obtención de la lista de ventas para que sea manejada por Hibernate.

Objetivo

Utilizar la capacidad de trabajar con consultas sql nativas parametrizadas de Hibernate.

Desarrollo

En esta ocasión no es mucho el trabajo, comenzaremos configurando:

ar.com.magm.web.primefaces.VentasBean

...
...

SessionFactory sessionFactory; 

public VentasBean() {
  jsfCtx = FacesContext.getCurrentInstance();
  bundle = jsfCtx.getApplication().getResourceBundle(jsfCtx, "msg");
  sessionFactory = HibernateUtil.getSessionFactory(); 
  // processList(null);
}

... ...


Solo agregamos una instancia de SessionFactory para poder trabajar con Hibernate en las instancias de esta clase.
Luego debemos modificar el método que genera la lista de ventas:


private void processList(Object args[]) {
  meses = bundle.getString("lbl.months").split(",");
  ventas = new ArrayList<Venta>();
  zonas = new ArrayList<String>();
  Session session = sessionFactory.getCurrentSession();
  Query query = session.createSQLQuery(sql);
  if (args != null) {
    for (int t = 0; t < args.length; t++) {
      query.setParameter(0, args[t]);
    }
  }
  List<Object[]> vtaTmp = query.list();
  for (Object[] vo : vtaTmp) {
    Venta venta = new Venta(vo[2].toString(), 
                            vo[3].toString(),
                            Integer.parseInt(vo[0].toString()),
                            Integer.parseInt(vo[1].toString()),
                            meses[Integer.parseInt(vo[1].toString()) - 1],
                            Double.parseDouble(vo[4].toString()));
    ventas.add(venta);
    if (!zonas.contains(venta.getZona()))
      zonas.add(venta.getZona());
  }

  /*
  ServletContext sc = (ServletContext) FacesContext.getCurrentInstance()
                                        .getExternalContext().getContext();
  Connection cn = (Connection) sc.getAttribute("datasource");
  try {
    PreparedStatement pst = cn.prepareStatement(sql);
    if (args != null) {
      for (int t = 0; t < args.length; t++) {
        pst.setObject(t + 1, args[t]);
      }
    }
    ResultSet rs = pst.executeQuery();
    while (rs.next()) {
      String zona = rs.getString("zona");
      Venta venta = new Venta(zona, rs.getString("cliente"), rs.getInt("anio"),          
                              rs.getInt("mes"), meses[rs.getInt("mes") - 1], 
                              rs.getDouble("ventas"));
      ventas.add(venta);
      if (!zonas.contains(zona))
        zonas.add(zona);
    }
  } catch (SQLException e) {
    e.printStackTrace();
  }
  */
}


Lo primero que haremos en este método es inhabilitar todo el código antiguo, en aquel en que utilizábamos JDBC. Se puede ver que hemos utilizado comentarios de bloque: /* .. */
Luego en la línea
Query query = session.createSQLQuery(sql);
Obtenemos un objeto Query, el cual nos permite trabajar con sentencias SQL nativas, el método recibe como parámetro la consulta, que no es ni más ni menos que la que ya estábamos utilizando:

SELECT    year(fecha) as anio,    month(fecha) as mes,    zona,    cliente,    sum(importe*cantidad) as ventas  FROM    dw_ventasfact v      INNER JOIN clientes c ON v.idCliente=c.idCliente      INNER JOIN zonas z ON z.idZona=c.idZona  WHERE    cliente like ?  GROUP BY    zona, cliente, anio, mes  ORDER BY    anio,mes,zona,cliente En el siguiente fragmento establecemos los valores para los parámetros, la diferencia más importante con el método anterior es que los parámetros comienzan desde 0, en JDBC es a partir de 1. if (args != null) {
  for (int t = 0; t < args.length; t++) {
    query.setParameter(0, args[t]);
  }
}
En la líneaList<Object[]> vtaTmp = query.list();
obtenemos una lista que en cada elemento contiene un arreglo de objetos que representa una fila, en nuestro caso una entidad de ventas. El orden de los elementos del array coinciden con lo definido en la consulta SQL, en nuestro caso:  [0]=año [1]=mes [2]=zona [3]=cliente [4]=ventas

El código que sirve para poblar la lista (el ciclo while) casi no ha cambiado, solo se reemplazó la línea que instancia la venta, ahora se utilizan los elementos del array y también se reutiliza la zona ya obtenida, por ello se quitó la primera línea en la cual se obtenía.

  Esta es toda la modificación que hay que realizar en cuanto a código, ahora solo falta crear sesiones para que puedan ser utilizadas en este componente para lo cual modificaremos HibernateContextListenerAndFiltercomo ya lo hemos hecho antes:   ... @WebFilter(urlPatterns = { "/TestHibernateConSpring", "*.xhtml" })  ...   Solo agregamos el patrón "*.xhtml" para que se creen sesiones ante peticiones de componentes JSF.   Bien, ya podemos probar y no notaremos ninguna diferencia, todo seguirá funcionando como antes del lado del cliente, solo que ahora Hibernate maneja algo más. En la consola podemos ver las sentencias SQL que Hibernate envía al motor.   Espero les sea de utilidad   Saludos