Hibernate

Usar JDBC es complejo y muy dependiente de la estructura de los datos. Sería más natural y mucho más sencillo trabajar directamente con objetos, pero es imposible con las BBDD relacionales, y las BBDD orientadas a objeto están todavía muy verdes.

La mejor opción entonces es utilizar un motor de persistencia, que es el componente software encargado de traducir entre objetos y registros. Un motor de persistencia de código abierto es Hibernate, que nos permitirá hacer cosas como poder guardar un objeto en la base de datos simplemente con session.save(miObjeto) o borrarlo con session.delete(miObjeto).

Usa el mecanismo de reflexión de Java, que permite a un objeto en ejecución examinarse y manipularse a sí mismo, en contra de, por ejemplo, JDO, que necesita que modifiquemos los archivos de las clases.

Vamos a tener un archivo properties (hibernate.properties) o un archivo xml (hibernate.cfg.xml) para la configuración, una serie de JavaBeans que son las clases a persistir y en las que cada campo se asociará con una columna de la BBDD, y un archivo xml por cada una de estas clases (NombreClase.hbm.xml) que indica el mapping entre objetos y relaciones.

Este sería el aspecto del JavaBean que representa una sucursal en una supuesta aplicación:

package net.mundogeek.ejemplo;

public class Sucursal {
  private String director, telefono;
  private long idSucursal;
  
  public Sucursal(){
  }
  
  public Sucursal(String director, String telefono, long idSucursal) {
    this.director = director;
    this.telefono = telefono;
    this.idSucursal = idSucursal;
  }
  
  public long getIdSucursal(){
    return idSucursal;
  }
  
  public void setIdSucursal(long idSucursal) {
    this.idSucursal = idSucursal;
  }

  // ...
  // getters y setters para telefono y director
}

Y este el del fichero de mapping de hibernate correspondiente:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="net.mundogeek.ejemplo.Sucursal" table="Sucursal">
    <id name="idSucursal" type="java.lang.Long">
      <column name="id_sucursal" />
      <generator class="native" />
    </id>
    <property name="director" type="java.lang.String">
      <column name="director" length="25" />
    </property>
    <property name="telefono" type="java.lang.String">
      <column name="telefono" length="25" not-null="true" />
    </property>
  </class>
</hibernate-mapping>

Como vemos la etiqueta class se utiliza para asociar nuestra clase a una tabla concreta de la base de datos. Las etiquetas que se sitúan por debajo de class nos permiten definir la relación entre las propiedades de la clase y las columnas de la base de datos. La etiqueta id se usa para identificar el campo que actuará como clave primaria e indicar el tipo que va a tener (Long en este caso), así como la columna de la base de datos en la que se almacenará el campo y la forma de generar la clave (en este caso, native, que depende de la base de datos que usemos; podríamos haberle indicado por ejemplo que simplemente fuera sumando 1 cada vez con increment, o incluso crear nuestra propia clase generadora). A continuación tenemos una serie de etiquetas property, una por cada propiedad, que funcionan de forma parecida a id, indicando el nombre de la propiedad de la clase (atributo name) su tipo (atributo type) y la columna a la que se mapea (atributo name de column).

Como sabemos, las tablas también pueden tener relaciones entre ellas. En Hibernate podemos declarar relaciones N:M mediante la etiqueta many-to-many, 1:N con one-to-many y N:1 con many-to-one.

Por ejemplo podríamos tener una tabla de trabajadores y querer indicar para qué sucursal o sucursales trabaja cada uno de ellos (N:M, many-to-many). Tendríamos entonces una tabla sucursal, una tabla persona, y una tabla persona_sucursal para relacionarlas.

Veamos cómo podemos tener una colección de trabajadores en la clase Sucursal y que Hibernate sea capaz de rellenarla viendo la estructura de la base de datos y nuestro archivo de mapping.

<set name="personas" table="persona_sucursal" cascade="save-update">
  <key column="id_sucursal"/>
  <many-to-many class="net.mundogeek.ejemplo.Persona" column="id_persona"/>
</set>

Los conjuntos se representan en el archivo mapping de hibernate mediante la etiqueta set (también tenemos otras colecciones como list, map, bag o array). Esta etiqueta va a tener un atributo name, con el nombre de la propiedad de la base de datos asociada; un atributo table, con la tabla mediante la que implementamos la relación (persona_sucursal) y un atributo cascade que nos indica qué hacer con las tuplas de la tabla persona relacionadas con una sucursal cuando se modifique o borre esta sucursal (save-update indica inserción y modificación en cascada, delete, borrado en cascada; all, todas las operaciones en cascada y none ninguna).

La etiqueta set va a contener una etiqueta key, en la que indicamos la clave ajena del objeto actual en la tabla que implementa la relación que es la que se utiliza para diferenciar las instancias de la colección y una etiqueta many-to-many que indicará la clase de los objetos que vamos a tener en la colección y cuál es la clave ajena a su tabla en la tabla persona_sucursal.

Si quisiéramos que la asociación fuera bidireccional (una colección de las sucursales en que trabaja en la clase Persona) tendríamos que añadir otra etiqueta set en el mapping de Persona, pero añadiendo en este caso un atributo inverse="true".

Las relaciones one-to-many y many-to-one funcionarían de forma parecida, solo que no necesitamos una tabla nueva, sino que tendremos una clave foránea de una de las tablas a la otra (si una persona sólo puede trabajar para una sucursal, Persona sólo necesita una propiedad de tipo Sucursal con la sucursal en la que trabaja y no una colección; el otro extremo, Sucursal, si necesitará una colección con las personas que trabajan en la sucursal). En Sucursal.hbm.xml tendríamos:

<set name="personas" table="persona">
  <key column="id_sucursal"/>
  <one-to-many class="net.mundogeek.ejemplo.Persona"/>
</set>

Y en Persona.hbm.xml:

<many-to-one name="sucursal" column="id_sucursal"/>

Ahora que ya hemos visto como indicarle a Hibernate la correspondencia entre nuestras clases y las tablas de la BBDD, vamos a ver cómo utilizaríamos esta API.

Lo primero que tendríamos que hacer para empezar a utilizar Hibernate sería crear un nuevo objeto Configuration para poder indicarle dónde se encuentra el archivo de configuración:

Configuration cfg = new Configuration();
cfg.configure(RUTA_ARCHIVO_CONF);

A partir del hibernate.cfg.xml podemos crea un SessionFactory, que es el objeto mediante el cual abrimos nuevas sesiones de Hibernate.

SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();

Para insertar objetos en la BBDD usaremos el método save(Object objeto) de Session, para insertar o actualizar si ya existe saveOrUpdate(Object objeto), para borrar delete(Object objeto) y para cargar un objeto desde la BBDD get(String clase, Tipo id) o load(String clase, Tipo id) que devuelven el objeto de la clase indicada por el primer parámetro y con identificador el segundo parámetro si es que existe en la BBDD.

Para hacer búsquedas en la base de datos podemos usar find(String consulta) que devuelve una lista con los resultados, o iterate(String consulta) que devuelve un iterador, o bien crear un objeto Query usando createQuery(String consulta) y llamar más tarde al método find() del Query. La consulta en todos los casos estará escrita en un lenguaje similar a SQL propio de Hibernate llamado HQL (Hibernate Query Language). Otra opción sería trabajar con objetos Criteria.

65 pensamientos en “Hibernate”

  1. Hola antes que nada muchas gracias por el espacio, mi problema es que recién estoy conociendo hibernate y no se como hacer una consulta y utilizar clausulas como where o alguna otra quisiera que me muestren un ejemplo sencillo desde ya muchas gracias

  2. huaauu lo anduve buscando hace tiempo gracias si podes pasarme mas material o un ejempllo de implementacion lo agradeceria mas! gracias saudos

  3. yo Tengo un problema, segun el compilador es con mi archivo hibernate.cfg.xml, me dice que el archivo no existe cuando hago la llamada desde un objeto.
    este es mi objeto que ingresa al archivo que toma la session:

    laipmichhelper consulta=new laipmichhelper();
    String Descripcion=request.getParameter(“desc_art”);
    out.println(Descripcion);
    saca.setDescripcion(Descripcion);

  4. Esta muy bien explicado, me sirvio de mucho y yo pense que era muy complicado muchas gracias con esto puedo empezar para aprender mas sobre hibernate tks.

  5. Si pidieran implementar un método en java que realice una validación del tipo de garantía asociada al préstamo dependiendo primeramente de su parametrización a nivel de producto y luego dependiendo del monto otorgado según las siguientes especificaciones:
    ((SI MONTO RECOMENDADO $. 10.000,00 Y GARANTIA PROPUESTA =HIPOTECARIA O = PRENDARIAS ENTONCES PRESENTAR CALIFICA) SI NO PRESENTAR NO CALIFICA)), como ustedes realizarían dicho meétodo haciendo uso de hibernate????

  6. Hola muy clara tu explicacion, comenze a trabajarlo hace un par de días, pero me he topado con el problema del formato decimal, tengo un objeto con una propiedad de tipo double, la cual despliego antes de almacenar con un valor 10.569, pero al ejecutar session.save(objeto), el valor guardado en la DB es 10569, es decir, no respeta el punto decimal, a excepción si utilizo la coma ‘,’

    ¿Como puedo cambiar el separador decimal ??

    Espero puedas ayudarme.

    Saludos

  7. Pingback: Software Hibernate My Eclypse para conectar a una base de datos con XML • GestioPolis

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.