
¿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).