miércoles, octubre 12, 2005

Hibernate, comienza el frio

¿Quién no ha hecho una aplicación en su vida que se conecte a una base de datos? Incluso quizás sea mejor pregunta: ¿Quién ha hecho una aplicación que no se conecta a una base de datos? Quizás a esta respuesta contestasen menos personas y nos ahorraríamos tiempo de contar manos en alza. Lo cierto es que para un programador, las bases de datos son fundamentales.
Casi desde el principio, en el mundo javero, se ha tenido en cuenta dicho hecho, y ya desde principios se diseñó JDBC para poder facilitar a los programadores el acceso a bases de datos. JDBC es una API que sirve para conectar a base de datos de manera independiente del tipo de base de datos uses.
Esto es extremadamente útil porque con un poco de elegancia en el diseño de la aplicación, puedes conseguir una aplicación que sea completamente independiente de la base de datos.
Hoy en día las bases de datos en su mayoría son bases de datos relacionales. Existen bases de datos orientadas a objetos pero en la práctica, las más usadas son las relacionales. Y lo cierto es que parece ser que esto va a seguir siendo así bastante tiempo (por lo menos no hay muestras de alguna tendencia que incite a pensar lo contrario).
Las bases de datos relacionales, tal y como indica su nombre, se basan en relaciones entre entidades. Concepto que dista mucho de lo que es la oop (abstracción, encapsulación, polimorfismo y herencia). El hecho de que exista dicha diferencia puede complicar la manera de conseguir que la aplicación persista correctamente los objetos de negocio en la base de datos.
Debido a esto se han creado frameworks de persistencia de objetos. Sirven para persistir los objetos de una forma transparente al programador.
¿Como funciona Hibernate? La verdad es que es bastante sencillo, como concepto, después las cosas se pueden complicar bastante si no se tiene un buen diseño de la base de datos. Si se quiere usar Hibernate se han de crear los objetos de negocio y sus relaciones. Después se deberá crear una serie de archivos xml que indican a hibernate qué objeto se guarda en qué tabla, indicando la relación entre propiedades del objeto y columnas de la tabla. Por ejemplo, yo tengo una clase Persona tal y como sigue:


package org.edvera.hibernateexample;

public class Persona {

private String nombre;
private String apellido;

public String getNombre()
{
return nombre;
}

public void setNombre(String nombre)
{
this.nombre = nombre;
}

public String getApellido()
{
return apellido;
}

public void setApellido(String apellido)
{
this.apellido = apellido;
}
}

Esta clase quiero que guarde sus datos en la tabla PERSONAS, que viene definida:

CREATE TABLE PERSONAS (
id int primary key auto_increment,
nombre varchar(32) not null,
apellido varchar(32) not null
);

Si quiero que hibernate me haga la persistencia (guardar) del objeto tendré que indicarle la relación entre el objeto y la tabla. Esto se hace mediante un archivo xml que llamaremos Persona.hbm.xml, como el que sigue:

<hibernate-mapping>
<class name="org.edvera.hibernateexample.Persona" table="PERSONAS">
<id name="id" column="id" type="int">
<generator class="native">
</generator>
</id>
<property name="nombre" type="java.lang.String" column="nombre"/>
<property name="apellido" type="java.lang.String" column="apellido"/>
</class>
</hibernate-mapping>


De esta forma ya tenemos mapeado el objeto con la base de datos. Nos queda crear otro archivo para configurar la conexión que ha de usar hibernate (hay varias maneras de hacerlo, yo voy a usar la más sencilla para mayor claridad). Este archivo se llama hibernate.cfg.xml y es el siguiente:


<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/bbdd</property>
<property name="connection.username">bbdd_user</property>
<property name="connection.password">bbdd_passwd</property>
<property name="connection.dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<!-- mapping files -->
<!-- ficheros relacionados con los productos -->
<mapping resource="org/edvera/hibernateexample/Persona.hbm.xml"/>
</session-factory>
</hibernate-configuration>


En este archivo se dan los datos para poder hacer la conexión (aquellos que son los elementos property de la session factory) así como los archivos de mapeos (nosotros solo tenemos uno que es el de Persona.hbm.xml).
Ahora que tenemos hibernate configurado y listo para servirnos, veamos como usarlo en el código. Vamos a hacer una clase con un método principal que usa hibernate para guardar en la base de datos una persona ejemplo.


package org.edvera.hibernateexample;

import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;


public class HibernateExample {

public static void main (String args[])
{
Configuration configuration = new Configuration(); //Objeto que guardará la configuración de hibernate
try
{
//Leemos el archivo de configuración de hibernate (que deberá estar en el classpath
configuration.configure();
//Creamos la factoria de sesiones
SessionFactory sessionFactory = configuration.buildSessionFactory();
//Obtenemos una sesion
Session session = sessionFactory.openSession();
//Creamos la persona y la dotamos de información
Persona persona = new Persona();
persona.setNombre("Perico");
persona.setApellido("ElDeLosPalotes");
//Usamos la sesion de hibernate para persistir el objeto Persona
session.save(persona);
//Nos aseguramos de que se guardan los datos de la sesión en la base de datos
session.flush();
//Cerramos la sesión
session.close();
}
catch (Exception e)
{
//Excepcion no esperada.
}
}
}


Como se puede ver, a pesar de la simpleza y poca utilidad del código, el resultado es un código más limpio, sin necesidad de usar sentencias sql en cosas tan triviales.
De todas maneras las cosas no son tan sencillas con hibernate como parecen. Hay que tener en cuenta de que hibernate guarda los datos del objeto en la sesión, y que hasta que no se hace un flush no se persisten realmente los datos. El hecho de que la sesión se interponga entre los datos y la base de datos obliga a tener mucho cuidado en como se gestionan las sesiones. Puesto que una sesión debe pertenecer a un único Thread y un único Thread no debería de tener más de una sesión porque en caso contrario no se puede asegurar la integridad de los datos (dos threads usando la misma sesión podrían estar poniendo en peligro los datos).
Espero que este artículo sirva como primer acercamiento a esta tecnología y que el lector, después de haberlo leido, tenga una noción de lo que son los famosos frameworks de persistencia así como una idea general de para qué sirve hibernate. Por supuesto no he hablado ni del 10% de lo que puede hacer Hibernate, pero no pretendo quitarle trabajo a los chicos de JBoss (XD).

9 comentarios:

Anónimo dijo...

Tus articulos siguen siendo muy interesantes, pero nos gustaria que, en lugar de tocar ligeramente todas las tecnologias, te curraras unas series de posts mas detallados. Mas que nada para que no pensemos que eres el tipico "enteradillo de foro"...


daMunkah. Alhamdulillah.

eTux dijo...

Jejejeje... entiendo tu comentario... pero tenía que introducir las tecnologias, todas ellas, para despues poder usarlas con ejemplos... de todas maneras gracias por el comentario y espero tener pronto ejemplo ilustrativos con todas las tecnologías que he comentado hasta el momento.

Anónimo dijo...

Etux:
Evidentemente,la didáctica es una de tus virtudes.Exelente el artículo,claro y preciso como siempre.
Quiero decirte que yo no voy a pensar que eres el "típico enteradillo de foro",pero creo haberte dicho ya que me gustaría verte en algo mas pesado.
Un saludo.

Anónimo dijo...

Si por algo mas pesado te refieres al proEvolution 5, estoy convencido de que muy pronto tendras tu articulo XD



daMunkah

Anónimo dijo...

¿Que tiene que ver un juego de soccer con lo que se está hablando?

Luis dijo...

muchas gracias por tu articulo, estoy empezando con hiberbate, y me ha ayudado mucho, moltes grasies!

eTux dijo...

Recomiendo encarecidamente que no se usen xdoclet sino anotaciones para evitar tener que usar los archivos de configuracion de mapeo de entidades hbm.xml.

Anónimo dijo...

Muy bueno, me ha aclarado mucho conceptualmente el tema de Hibernate.
gracias

Ronaldo dijo...

Disculpa cuando dices que no es ni el 10% de lo que es hibernate,
nos puedes describir, que mas puede hacer hibernate, a simple vista nada mas, sin entrar en detalles.
:)
Gracias, soy nuevo en hibernate.!