Volvemos con la segunda parte de “Conociendo un ORM”, continuando el desarrollo que dejamos a medias con Hibernate. Una vez realizada la configuración, los modelos y sus mapeos correspondientes solo nos queda apoyarnos de toda la configuración para poder obtener, insertar, editar y eliminar los datos de la aplicación haciéndolos persistir en la base de datos.

Hibernate ORM

Un buen hábito de desarrollo es construir una clase HibernateUtil que se apoye en el patrón Singleton. El objetivo de emplear este patrón es el de garantizar que una clase solo tenga una instancia en la aplicación, y proporcionar un único punto de acceso global a ella, Hibernate trabaja con sesiones y genera una instancia de la base de datos para trabajar con ella, por lo tanto es lógico y un buen hábito de trabajo cuando se trabaja con éste framework de persistencia crear esta clase que proporciona un único punto de acceso a dicha instancia, evitando crear una sesión distinta desde distintos puntos de la aplicación que finalmente nos puede llevar a generación de errores y consumo innecesario de memoria.

Para ello se desarrolla la clase “HibernateUtil” en la cual declaramos un atributo “static” del tipo “SessionFactory” asegurándonos de que solo existe una instancia. Además este atributo se define como final para que no pueda ser modificado ni alterado por ningún cliente que lo referencie. Gracias al patrón Singleton obtenemos un acceso controlado de la sesión, las clases que deseen una referencia a la sesión única la obtendrán llamando al método estático getSessionFactory() de la clase:

public class HibernateUtil {

	private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new AnnotationConfiguration().configure()
                    .buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

A continuación debemos definir unas clases manejadoras que nos proporcione las operaciones CRUD básicas. Aquí podemos ver como cada función obtiene la Sesión correspondiente através de Hibernate Util, y esta sesión nos proporciona los métodos básicos para las operaciones CRUD (Crear, Obtener, Actualizar y Eliminar)(Create, Read, Update and Delete). Es importante destacar que para realizar consultas mas complejas Hibernate proporciona ciertas herramientas como los Criteria o un lenguaje especial llamado HQL. Aquí muestro las funciones básicas de los Manager:

public class ClienteManager {

    public Cliente add(Cliente cliente) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.save(cliente);
        session.getTransaction().commit();
        return cliente;
    }

    public Cliente update(Cliente user) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.update(user);
        session.getTransaction().commit();
        return user;
    }

    @SuppressWarnings("rawtypes")
	public Cliente getClienteById(String id) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Criteria crit = session.createCriteria(Cliente.class).add(Restrictions.eq("id",id));
        List result=crit.list();
        session.getTransaction().commit();
        if (result.isEmpty())
        		return null;
        else
        	return (Cliente)result.get(0);
    }

    public Cliente delete(Long id) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Cliente contact = (Cliente) session.load(Cliente.class, id);
        if(null != contact) {
            session.delete(contact);
        }
        session.getTransaction().commit();
        return contact;
    }

    @SuppressWarnings("unchecked")
	public List list() {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        List contacts = null;
        try {

            contacts = (List)session.createQuery("from Cliente").list();

        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        session.getTransaction().commit();
        return contacts;
    }

}

public class PedidosManager {

    public Pedido add(Pedido pedido) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.save(pedido);
        session.getTransaction().commit();
        return pedido;
    }

	public List getPedidoByUserId(int id) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Criteria crit = session.createCriteria(Pedido.class).add(Restrictions.like("cliente_id", id));
        List result=crit.list();
        session.getTransaction().commit();
        return result;
    }

	public Pedido getPedidoById(int id) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Criteria crit = session.createCriteria(Pedido.class).add(Restrictions.like("id", id));
        List result=crit.list();
        session.getTransaction().commit();
        return (Pedido) result.get(0);
    }

    @SuppressWarnings("unchecked")
	public List list()
	{
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        List pedidos = null;
        try
        {
            pedidos = (List) session.createCriteria(Pedido.class).list();
        }
        catch (HibernateException e)
        {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        session.getTransaction().commit();
        return pedidos;
    }

	public Pedido update(Pedido pedido)
	{
		 Session session = HibernateUtil.getSessionFactory().getCurrentSession();
	        session.beginTransaction();
	        session.merge(pedido);
	        session.getTransaction().commit();
	        return pedido;
	}
}

Procedamos a ver como se emplea esta arquitectura de clases. Este ejemplo sencillo crea un nuevo objeto de la clase Cliente, estableciendo con sus métodos set los distintos atributos de este y finalmente pasándo el objeto al Manager para que se encargue de persistirlo en la base de datos:

                Cliente cliente = new Cliente();
		cliente.setApellidos(getApellido());
		cliente.setNombre(getNombre());
		cliente.setDomicilio(getDomicilio());

		cliente = clienteManager.add(cliente);

Espero que hayáis disfrutado con estos pequeños ejemplos. Volveré a tratar el tema de los ORM con más profundidad analizando alguna otra herramienta o describiendo características más avanzadas de Hibernate. Aún así os comparto la documentación oficial de la versión 3.5.7 que viene muy bien explicado y con ejemplos

[googleplusauthor]

Artículos relacionados...

Sobre El Autor

Coordinador en AnalyticaWeb.com Me encanta el SEO y la Analítica Web. Emprendedor y autodidacta que con pasión intenta alcanzar los máximos de su proyección. Disfruto convirtiendo datos en negocio.

Artículos Relacionados

6 Respuestas

  1. david

    hola.

    me pregunto como programas una consulta select x ejemplo con una tabla principal y una auxiliar????

    contratos(anno,mes,id_municipio,valor)

    aux_municipios(id,descripcion)

    Responder
  2. david

    lo pregunto xq el ejemplo q has puesto es el tipico per para algo mas complejo con varias tablas relacionadas, obtener el ultimo dato, hacer inner join entre 5 o 6 tablas a la vez, es q no veo la ventaja.

    gracias
    saludos

    Responder
    • Adrián Alonso Vega

      Hola David, lo primero de todo gracias por colaborar.

      Supongo que te refieres a ir recorriendo distintas tablas para obtener datos. Como bien dices este ejemplo es el típico relación de 1 a N entre dos tablas. El desarrollo completo tenía mas relaciones, por ejemplo los pedidos además tenían N productos y un estado.

      Existen varias formas de hacerlo, pero por ejemplo cuando recuperas a través del EntityManager un elemento hay dos formas de hacerlo, una que sería activando el parámetro lazy, en el cual le dices que la conexión es perezosa y solo tendrá en cuenta para recuperar los atributos simples, no las relaciones, evitando largos join. Si por otro lado desactivas este parámetro para una relación se harán consultas recursivas con join entre las tablas relacionadas obteniendo todos los datos, siendo para tí transparente,.

      Es una gran ventaja que al recuperar un elemento te abstraigas de todas las tablas que tienes que recorrer, pero claro por otro lado es pesado ya que Hibernate tiene que ir recorriendo todos los elementos de la base de datos. Depende del objetivo de tu aplicación o tu funcionalidad te merece la pena cargar todo o solo ir cargando los datos que te sean necesarios y recuperar datos relacionados con pequeñas consultas que lanzaras en momentos determinados

      Por cierto para el tema de lazy mira los archivos de mapeo del artículo anterior.

      Muchas Gracias por leernos y colaborar. Cualquier dudas que tengas no dudes en comentarla 😉

      Responder
  3. David

    Hola.

    Gracias por su comentario. Mucha información, tengo que ir mirando lo que me comentas con detenimiento.

    Solo una cosa. Yo utilizo normalmente eclipse 3.4 / 3.7. Existe algún plugin (sé que para myEclipse sí) que me permita hacer los cambios en los ficheros hbm, etc.. cuando hago cambios en la base de datos y que lo haga de forma automática. Las pruebas que he hecho al final me conducen a tener que tocar los ficheros de forma manual.

    Gracias.
    Salu2

    Responder
  4. La era de los ODM

    […] he decidido mezclar distintos temas de los que he escrito anteriormente: los Mapeos Objeto Relacionales y las Bases de Datos orientadas a Documentos. El patrón de mapeo de datos de la base de datos es […]

    Responder

Hacer Comentario

Su dirección de correo electrónico no será publicada.