Mi granito de java: Introducción a Hibernate

domingo, 14 de agosto de 2011

Introducción a Hibernate

En este post voy a hacer una introducción a Hibernate. Tan sólo un Hola Mundo para que se entiendan los conceptos principales. Luego más adelante haré otras entradas para profundizar un poco más sobre este framework.

Hibernate.

“Hibernate es una herramienta de Mapeo objeto-relacional (ORM) para la plataforma Java (y disponible también para .Net con el nombre de NHibernate) que facilita el mapeo de atributos entre una base de datos relacional tradicional y el modelo de objetos de una aplicación, mediante archivos declarativos (XML) o anotaciones en los beans de las entidades que permiten establecer estas relaciones. Hibernate es software libre, distribuido bajo los términos de la licencia GNU LGPL. “ - Wikipedia.

Hibernate es un framework que agiliza la relación entre la aplicación y la base de datos. De todos los frameworks ORM que he utilizado, sin dudas es el más completo.
Para aprender Hibernte es necesario tener los conocimientos mínimos de SQL y Java. Conocer JDBC es recomendable. Se puede bajar (en principio con bajar Hibernate Core alcanza) de www.hibernate.org



¿Por que usar un framework ORM?

Cuando uno desarrolla una aplicación se dará cuenta que en la gran mayoría de los casos todo termina siendo un conjunto de ABMs (alta, baja, modificación de datos) para luego poder consultarlos. Para ello se utiliza una base de datos, donde existirán muchas tareas repetidas: por cada objeto que quiero persistir debo crear una clase que me permita insertalo, eliminarlo, modificarlo y consultarlo. Salvo aquellas consultas fuera de lo común, el resto es siempre lo mismo. Aquí es donde entra a jugar un rol importante un ORM: con solo configurarlo ya tiene todas esas tareas repetitivas realizadas y el desarrollador solo tendrá que preocuparse por aquellas consultas fuera de lo normal.

¿Como funciona Hibernate?

Básicamente el desarrollador deberá configurar en un archivo XML o mediante annotations donde corresponde un atributo de una clase, con una columna de una tabla. Es una tarea relativamente sencilla donde existen herramientas que lo hacen por nosotros. En principio voy a realizar los ejemplos con archivos xml y luego, en otro post, los haré mediante annotations.

Configuración.

Vamos a hacer un paso a paso para dejar todo listo. Primero vamos a colocar los jars en el proyecto. Aqui van los de hibernate (que vienen en la carpeta lib de la distribución), más el del driver correspondiente a la base de datos que esten utilizando. Yo voy a utilizar DB2. A continuació voy a colocar los jars necesarios. He colocado los de Hibernate + DB2 + MySQL por si alguno la usa.

Luego vamos a crear una sencilla tabla en la base de datos:
Para MySQL:
CREATE TABLE `autos` (
`IDAUTO` int(10) unsigned NOT NULL auto_increment,
`MARCA` varchar(255) NOT NULL default '',
`MODELO` varchar(255) NOT NULL default '',
PRIMARY KEY (`IDAUTO`)
)

Para DB2:
CREATE TABLE hib.AUTOS (
IDAUTO BIGINT NOT NULL,
MARCA VARCHAR(255),
MODELO VARCHAR(255)
);
CREATE UNIQUE INDEX SQL1108120858221120 ON hib.AUTOS (IDAUTO ASC);
ALTER TABLE hib.AUTOS ADD CONSTRAINT SQL1108128085281980 PRIMARY KEY (IDAUTO);


El siguiente paso es configurar un SessionManager que me permite obtener sesiones y transacciones para trabajar con la base de datos. En este caso haremos uno sencillo, que no sirve para trabajar en producción, pero que nos permite realizar nuestros ejemplos.
Aca les dejo la clase, comentada para que se entienda de donde salen todos los datos.

package configuracion;

import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
 
public abstract class SessionManager {
   
    public static Session getSession() throws HibernateException{
        // Instancia un objeto del tipo Configuration
        Configuration config = new Configuration();
       
        // Registra las clases a mapear en la configuracion
        registerMappers(config);
       
        // Establece las propiedades de configuracion
        config.setProperties(getHibernateProperties() );
       
        // Retorna una sesion de trabajo
        return config.buildSessionFactory().openSession();
    }
   
    private static Properties getHibernateProperties(){
        // Instancia un objeto del tipo Properties.
        Properties props = new Properties();
       
        // Establece el driver de conexion dependiente del RDBMS.
        //para MySQL seria:  props.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
        props.put("hibernate.connection.driver_class", "com.ibm.db2.jcc.DB2Driver");
       
        // Establece la url de conexion, donde al final va el nombre de la BD
        //para MySQL  props.put("hibernate.connection.url", "jdbc:mysql://localhost/testHibernate");
        props.put("hibernate.connection.url", "jdbc:db2://localhost:50000/sample");
               
        // Establece el usuario.
        props.put("hibernate.connection.username", "db2admin");
       
        // Establece la clave.
        props.put("hibernate.connection.password", "db2admin");
       
        // Establece el dialecto a utilizar. Es necesario determinarlo ya que la implementación
        // de SQL puede variar con cada motor de base de datos.
        // Para MySQL sería: props.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        props.put("hibernate.dialect", "org.hibernate.dialect.DB2Dialect");
         
        // Retorna las propiedades
        return props;
     
    }
   
    // Cada clase mapeada deberá aparecer aca.
    private static void registerMappers(Configuration config) throws MappingException
    {
        config.addResource("negocio/Auto.hbm.xml");
    }
 }

Como verán, he configurado el SessionManager de manera programática. Obviamente lo ideal para un proyecto laboral es hacerlo con archivos de configuracion. Aca hay un ejemplo: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html

Hasta aquí hemos terminado de confgurar Hibernate. Ahora podemos comenzar a utilizarlo. Para ello, haremos la clase Auto y su correspondiente archivo xml



Y, ahora veremos el archivo auto.hbm.xml. La extensión hbm.xml es por conveción. Este archivo representa la forma de relacionar una clase con una tabla. Existirá un hbm.xml por cada clase que desee mapear. Por lo general, se acostumbra dejar el archivo xml en el mismo paquete de la clase mapeada.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class  name="negocio.Auto" table="autos">
        <id name="id" column="idauto">
            <generator class="increment" />
        </id>
        <property name="marca" />
        <property name="modelo" />
    </class>
</hibernate-mapping>

Listo, ya tenemos todo para realizar las primeras pruebas. Pero antes voy a explicar que es cada cosa en el xml:
  1. hibernate-mapping es la raíz del documento y, por ende, todos los tags quedan contenidos dentro de este tag.
  2. El tag class es general: nombra la clase y la tabla.
  3. El tag id representa el atributo que se relaciona con la clave primaria. Su atributo name hace referencia a como se llama el id en la clase (en nuestro caso da la casualidad que se llama id) y el atributo column representa la columna en la base de datos.
  4. El tag property es utilizado para los atributos que no son clave primaria. Sus atributos más importantes son name y column. Si el nombre del atributo coincide con la columna, no es necesario especificar a ambos. Con especificar name es suficiente.
  5. El tag generator esta contenido dentro de id y representa la forma de generar la clase primaria al insertar un nuevo registro. Puede tomar diversos valores pero los más comunes son:
  • increment: para las claves autoincrementales.
  • sequence: para los secuenciadores.
  • assign: para los casos donde la BD no generá la clave primaria, sino que el objeto es quién la determina.

A probar!


Hemos insertado un auto. Tan sencillo como eso, ejecutar el método save.
Vamos a actualizarlo: ahora lo convertiremos en C4:


Y, por último, eliminaremos el registro:

Algunas últimas aclaraciones:
  • No he hecho consultas mediante Hibernate porque habría que profundizar un poco más y prefiero dejarlo para más adelante.
  • Para actualizar un registro es necesario colocarle el id a la clase. En este caso era un Long, por lo que tuve que hacer setId(1L).
  • Hibernate elimina por id de manera automática. Por ello, con solo colocarle el id al objeto auto es suficiente. Para eliminaciones más complejas hay que tirar un poco más de código.
Bien, hasta aquí llego nuestro pequeño ejemplo. Cuando tenga un poco más de tiempo voy a profundizar sobre este framework.

10 comentarios:

Anónimo dijo...

Max, la verdad que tu blog esta muy bueno, yo tengo uno donde recopilo informacion de desarrollo y queria publicar un link a tu pagina porque me parecio muy util,ademas asi no te robo tus publicaciones jeje!!
Felicitaciones por el blog!!

Max dijo...

Si, no hay problema, muchas gracias por tus comentarios!

apuntesJavaWeb dijo...

Excelente, muy util, felicitaciones por el gran trabajo

Max dijo...

Muchas gracias, muy amable!

Anónimo dijo...

Muchas gracias amigo.. funcionó perfecto

Anónimo dijo...

Gracias por el aporte!

Anónimo dijo...

Hola me podrias ayudar con una duda!? mi correo es kyth_17@hotmail.com agradeceria mucho

Max dijo...

ok ahora te mando un mail perdon por la tardanza, blogger no me envia un mail cuando hay un comentario

Anónimo dijo...

a bueno

Anónimo dijo...

ahora te mando un mail