Hibernate permite el ahorro de codificación, a cambio de un poco de retardo del sistema en tiempo de ejecución, no todo es miel sobre hojuelas, sin embargo, este tiempo es pequeñisimo de cualquier forma.
La manera en que Hibernate mapea los objetos para guardar sus datos en una base de datos no es tan complicado, en base a un archivo de mapeo (con terminación .hbm.xml) se indican se indica la relación entre un atributo y una columna en la tabla de la base de datos, opcionalmente se especifica el tipo de dato entre otras opciones. Lo que es necesario para la consistencia es la llave primaria, en un objeto sencillo no hay necesidad de esto, pero en el modelo relacional de base de datos sí. Lo que podemos indicar es un atributo del objeto como llave primaria y general el dato nosotros o permitir que Hibernate lo genere por nosotros, existen varias opciones aquí, como por ejemplo, generado por usuario, por fecha, secuencial, etc.
Aquí un ejemplo de una clase simple, esta clase debe tener métodos getters y setters, un Java Bean de lo más normal, además de un constructor sin argumentos:
public class Mensaje {
private Long id;
private String mensaje;
private Mensaje siguiente;
public Mensaje(){}
public Mensaje(String s){
mensaje=s;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMensaje() {
return mensaje;
}
public void setMensaje(String mensaje) {
this.mensaje = mensaje;
}
public Mensaje getSiguiente() {
return siguiente;
}
public void setSiguiente(Mensaje siguiente) {
this.siguiente = siguiente;
}
}
Y su archivo de mapeo, mensaje.hbm.xml (el nombre es opcional, pero es una buena medida el indicar el mismo nombre que el de la clase que mapea):
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//hibernate/hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="Mensaje" table="MENSAJES">
<id name="id" column="id" type="long">
<generator class="increment"/>
</id>
<property name="mensaje" column="mensaje"/>
<many-to-one name="siguiente" cascade="all" column="siguiente"/>
</class>
</hibernate-mapping>
Primero observamos la cabezera general de un archivo xml.
Luego aparace la etiqueta hibernate mapping, la raíz de nuestro archivo.
Luego varias tags:
class: Indica la clase que vamos a mapear con todo y su paquete y el nombre de la tabla de la base de datos.
id: Aquí damos la especificación de la llave de la tabla, en el ejemplo eleguimos el atributo id de nuestra clase e indicamos que será mapeado al campo id (del mismo nombre, no hay problema) y del tipo long.
generator: Dentro del indicador de llave primaria, indicamos como será formada la llave, en este caso increment genera un número secuencial en la tabla para cada registro insertado.
proprety: Para cada uno de los atributos extras. No solo se manejan tipos simples, también pueden ser indicados objetos, esto se verá en otra entrada del blog.
many-to-one: Es el tipo de relación que se guarda con otras tablas, o en este caso, con ella misma. Se indica el atributo y el campo de la tabla y en este caso el tipo de relación es de cascada, que significa el tipo de acción de relación en cascada.
Listo, esto se repetira para cada clase con persistencia en nuestro sistema.
Ahora el archivo que nombraré como maestro de configuración de Hibernate, el hibernate.cfg.xml.
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//hibernate/hibernate Configuration DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:hsql://localhost/testdb</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="show_sql">true</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="Mensaje.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Un archivo de configuración que especifica la configuración del driver, la conexión con la base de datos, los formatos de conexión, los dialectos con que se comunica el sistema con la base de datos, extras y los archivos de mapeo. Este archivo debe encontrarse en el classpath.
Si ya se han utilizado conexiones con base de datos, la mayoría de las líneas serán muy explicativas por si mismas, la primera indica el driver que utilizamos para la conexión, el segundo, el url, la url formada por jdbc : el manejador de base de datos que usamos : abreviación : especificaciones de conexión, investigar la url que debes escribir de acuerdo a tu manejador no debe ser difícil con Google. Seguidamente el usuario y el password para conectarnos. También podemos indicar que se muestre en consola el sql que genera hibernate para realizar sus operaciones. Los demás son especificaciones, si vemos hay un update, indicando una actualización automatica de los objetos que una vez guardados cambian sus valores en el sistema. Por último, todos y cada uno de los .hbm.xml que ya creamos para nuestras clases. Este archivo también puede venir en sabor .properties.
Por último, el código Java que hace uso del objeto Java y que lo persiste:
import java.util.Iterator;
import java.util.List;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
public class Raiz {
private static SessionFactory sessionFactory;
private static Session session;
private static Transaction tx;
public static void elDos(){
Mensaje message =
(Mensaje) session.load( Mensaje.class, new Long(1) );
message.setMensaje("Saludos terricolas");
Mensaje nextMessage = new Mensaje("Llevenme con su lider (por fis)");
message.setSiguiente( nextMessage );
}
public static void elUno(){
Mensaje message = new Mensaje("Hola Mundo");
session.save(message);
}
public static void revisar(){
List messages = session.createQuery("from Mensaje as m order by m.mensaje asc").list();
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Mensaje message = (Mensaje) iter.next();
System.out.println( message.getMensaje() );
}
}
public static void main(String[] args) {
Raiz instance = new Raiz();
try {
System.out.println("Iniciando Hibernate");
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
tx = session.beginTransaction();
elUno();
//elDos();
revisar();
tx.commit();
session.close();
System.out.println("Finalizando");
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
Hay un número importante de conceptos/objetos aquí:
Configuration: Encargado del arranque de Hibernate, se sirve del hibernate.cfg.xml para inicializar la conexión y levantar todo Hibernate.
SessionFactory: Nuestro generador de sesiones con la base de datos, estás son caras de establecer, pero son reutilizables, además de permitirnos conectarnos con otras base de datos al mismo tiempo.
Session: La sesión activa al momento, sobre la cual guardaremos, recuperaremos, consultaremos, etc.
Transaction: Operaciones atómicas, esto es opcional, pero yo he tenido problemas cuando no la utilizo, todo lo que se hace dentro de un beginTransaction y un commit, o se hace todo o no se hace nada.
No hay comentarios.:
Publicar un comentario