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
.
Muy buen resumen, lo vamos a usar
Si le resulta útil al menos a una persona ya me doy por satisfecho 🙂
Yo lo tengo que usar dentro de un par de meses para un proyecto, así que me lo «apunto» en los marcadores 😉
Gracias!!
Muy bueno.
Supongo que no será útil para todos los geek pero en mi caso sí que me interesa.
Una excelente introducción. Yo solo he trabajado con iBatis, y tu explicación ha servido para hacerme una idea muy clara de como funciona Hibernate. Añadido a del.icio.us 😉
Saludos
Muy buena intro, haber si de estas empiezo a utilizarlo en mis desarrollos.
saludos
Excelente!!! me ayudo mucho a aclarar muchas dudas…
Sencillo y presciso. Buena explicacion. Felicitaciones Amigo. Espero tus siguientes aplicaciones.
Saludos
Alguien tiene el hello world en Hibernate??No me aclaro con los mapeos y me gustaria verlo reflejado en un ejemplo. A ver si alguien me puede ayudar. He mirado por inet, y los k hay les falta algo o estan mal explicados. Os lo agradecere
Gracias
como diablos hago para hacer una consulta y me la guarde en una lista para mostarala al usuario
Estoy tratando de usar Hibernate con MySQL, pero en realidad no tengo un BD «como Dios manda» sino un conjunto de tablas inconexas, no aplica many-to-one, ni nada de eso, no hay Primary Keys… es un desastre, pero no puedo modificarla… Then, debo trabajar con ella tal cual… El punto es que no paso del buildSessionFactory… Por alguna razón que no entiendo no puede crear la bendita Session…
Puedes darme alguna luz???
Hola, Alda. No se si te sirve de algo ahora mi respuesta ya que ha pasado un tiempo :D. Pero x si alguien busca por internet algo parecido a tu problema te pongo lo q creo q seria la solución.
Por un lado mata al que hizo la base de datos :P.
Luego si tienes tablas inconexas (nunca lo habia visto :O ) Tabien tendras que tener objetos inconexos. De esta manera si tu tienes tu sucursal que tiene su personal (supongo que tendra la id o algo asi del personal) pero no esta unido a la tabla personal por ningun foreing keig (o algo asi) entonces yo me crearia un objeto sucursal con los mismos datos que mi tabla y un objeto personal con sus datos igual que en la tabla.
Luego al guardar con hibernate trabajaria igual q en sql por un lado rellenaria los datos de sucursal (1, «Paco», «987909090», 2) y por otro los de personal (2, «Pepito de los palotes», …) pero tendras que ser tu la que compruebe que no haya errores de claves externas incorrectas y cosas asi asi que tendrias que hacer primero un find (o un sql con lo que quieras) para ver si existe el trabajador 2 y luego hacer ambos sabes.
Esto es lo que creo, no se si me explicado bien
Algo como
public class Sucursal {
private String director, telefono;
private long idSucursal,personal ;
//… Setters y Geteers
}
public class Personal{
private String nombre;
private long id;
//… Setters y Geteers
Sin ligar ambos como si fueran objetos que no tienen nada que ver.
Luego,
Datastore ds = Hibernate.createDatastore();
ds.storeClass(Sursal.class);
SessionFactory sessionFactory =ds.buildSessionFactory();
Session session = sessionFactory.openSession();
// Crear sucursal nuevo en bd
Sucursal newSuc = new Sucursal();
newSuc.setIdSucursal(1);
newSuc.setDirector(«Paco»);
newSuc.setTelefono(«000000000»);
newSuc.setPersonal(2);
//Crear personal bd
Persona newPer = new Personal();
newPer.SetId(2);
newPer.setNombre(«Pepito»);
//Guardar ambos
session.save(newPer);
session.save(newSuc);
Antes de hacer los saves es cuando tendrias que comprobar la integridad de la bd en este caso no hace falta pq introduzco las dos tablas y puedes ver que hay un personal con id 2 en la tabla personal. Pero si tuvieras que insertar personal que ya existiera en la bd tendrias que comprobar manualmente si existen.
Además las sql que hagas para solo sucursal o solo personal te valdra el metodo find o load pero si quieres sacar el nombre del personal por sucursal tendras que hacer una sql manualmente o sacar por un lado los datos de la sucrusal y por otro el de sus empleados y luego mostrarlos tu.
HASTA LEG
si buen resumen en mi trabajo usamos Hibernate como framework para la base de datos aveces dentro del hibernate tmb usamos el metodo hibernateTemplat().saveall o sino deleteall o sino creamos metodos donde creamos obejtos del tipo Criteria para jalar de la base de datos y y si queremos del agregamos Restriccion q seria en SQL un WHERE pasandole como parametro en («nombre_campo_columna»,variable) y metemos esa consulta en un List propio del objeto criteia es decir si creamos Criteria criteria = session.createCriteria(Mi_Clase.class);
hay toy extrayendo todo y luego aca
Criteria criteria = session.createCriteria(Mi_Clase.class)
criteria.list();
hay toy metiendo todo lo extraido de la base de datos de esa clase ya mapeada a una lista q en un metodo se pudiera retornar para su uso
por ejemplo
ListaPruebaCriteria = getMiclaseCriteria();
el metodo getMiclaseCriteria() me estaria traendo toda la data de tabla con la cual la clase llamda Mi_Clase a sido mapeada cave resaltar q al meter a la lista la data jalada de la tabla se a metido a la lista una serie de objetos del tipo Mi_Clase con sus campos debidamente seteados con la data de la base de datos cada campo de la base de datos con registro se a seteado a cada cada variable de la clase Mi_Clase esa relacion se debe al mapeio hecho de esa clase como ya se explico mas arriba en esta web ahora para extraer cada objeto de la lista y a la ves extraer cada dato seteado a ese obejto se puede hacer lo siguiente un for de la siguiente forma:
for(Iterator iterMi_Clase = ListaPruebaCriteria.iterator(); iterMi_Clase.hasNext(); ){
//se procede al Casteo de la Lista al Objeto
//Mi_Clase
Mi_Clase mi_clase =
(Mi_Clase)iterMi_Clase.next();
/*con eso recorremos cada campo de la lista q obtuvmos del criteria traido de la BD y el casteo nos va permitir usar los metodos Get y Set del objeto Mi_Clase de la siguiente manera*/
String nombre = mi_clase.getNombre();
}
buenos amigos espero q les aya servido de algo este pequeño resumen de como poder usar el criteria del Hibernate
srs, estoy recien ahciendo una investigacion sobre hibernate,spring,struts, ejbv3.0,jsf. para una propuesta de desarrollo ..
mi pregunta.
cuales son las deficiencias de Hibernate con respecto a trabajar con EJBv3.0 y JDBC?
he trabajado bastante tiempo con j2ee, pero como recien estoy investigando me gustaria que me ayudases en poder tener una respuesta tecnica a lo que pregunto.
atte.
Claudio Nuñez
Bastante resumido me recordaste que tenia que hacer el mapping en el hibernate 😛
hola, he leido mucho sobre hibernate y me gustaria trabajarlo pero cuando le he tratado de descargar desde su sitio oficial el archivo baja corrupto, si algui me podria orientar en donde lo puedo descargar, gracias….
me gusta mucho lo voy a usar para mi tesis
Alguien puede darme alguna ventaja real del uso de hibernate sobre jdbc?, no sólo el hecho de poder persistir objetos directamente.
Gracias!!
Hibernate es muy bueno con el mundo objeto-relacional, para trabajar con objetos puros, la librería efectiva y eficiente para Java y .Net es el db4o… eso si trabajan con objetyos 100% puros…
Buena info.
quiero recuperar una lista de cuentas pero al momento que la ejeciuto me sale este error
en el Dao trabajo con esta consulta, la relacion de many to many
Query consulta = sesion.createQuery(«from Cuenta cuenta where rol =? and cuenta.usuario.apellidos like ? » );
List listaC = (List) su.recuperar(r1,»Ve»);
for (Cuenta cuenta:listaC)
System.out.println(listaC);
el error es este:
Exception in thread «main» java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to edu.unl.comun.negocio.modelo.Cuenta
me pueden ayudar donde esta la falla en la consulta o cuando deseo recuperar
tiene que ver con problemas de Casting mas bien es eso en que parte a saber!!!
el hibernate te da la «»»gran ventaja»»» de no tener que utilizar JDBC o bien, simplemente no te haces dependiente de tomcat, solo requieres programar en objetos planos un poco de xml y HSQL que es el lenguaje de consultas para Hibernate, para todo esto requieres de conceptos como VO y BO que significan Value Object y Bussiness Object respectivamente. Todo esto es muy interesante
muy buena esta intro! me acabo de poner con Hibernate y no había oído en mi vida ese nombre. Esto me ha servido para saber cómo va y por dónde hay que agarrarlo.
muchas gracias
Esta bueno pero ¿como configuras la propiedad en el .cs? ya que cuando lo quiero probar me tira error.
Gracias
muy interesante este articulo gracias por compartirlo
Quisiera que un manual de hibernate en español
Agradezco que haya tipos como usted, que entienden la belleza de compartir su conocimiento. Esta de puta m… este artículo, me ha ayudado un chingo.
Espero tener la suerte de encontrarme con otro artículo de tan buena calidad en otro momento.
Alguien me puede ayudar con una aplicación pequeña funcionando con struts e hibernate….
Por fin algo de hibernate explicado como la gente, gracias, se va a mis bookmarks
Buenas.
Gracias por el tutorial.
En respuesta a las ventajas de Hibernate…
Hibernate es la implementación de una capa de persistencia. Esto tiene como ventajas:
1. La independencia del sistema gestor de base de datos a utilizar. Como se describe en el tutorial. El lenguaje para realizar Querys es HSL (propio de Hibernate). Esto permite que no haya que cambiar nada de código para cambiar de Sistema Gestor de Base de Datos. Solo cambiar un parámetro en el fichero de configuración de Hibernate.
2. Hibernate implementa una especie de caché, guardando datos en su sesión. Esto permite liberar la carga a la base de datos y permitir así multitud de consultas simultaneas sin colapsar la base de datos.
Un saludo.
El problema de mucha gente, es que sabe mucho de una determinada cosa, pero luego no saben explicarla, a ti compañero no te pasa eso en absoluto.
Muchas gracias por tu aporte.
Muy bueno el detalle de Jesse James… pero cesar ha planteado una cuestion que no he visto que la hayan respondido y la cual me esta sucediendo a mi tambien: es con respecto al casting, tambien obtengo el mismo error:
Product prod = (Product) itr.next();
java.lang.ClassCastException: [java.lang.Object; cannot be cast to myapp.Product]
He encontrado un par de foros donde se toca el tema pero no encuentro solucion ya voy por el segundo dia de no poder resolver esto…
Gracias por el consejo
Intereseante la informacion,me va a ser de gran utilidad
hola:
estoy trabajando con la version net de hibernate, llamada nhibernate, parecio facil al inicio y rapido con sus save y saveorupdate para guardar datos…
pero es un framework muy malo (como sea que se llame), en sus proyectos no lo usen, bueno si no quieren borrar en cascada o no trabajaran con procedimientos almacenados, la verdad… igual es pesimamente malo…
el asunto es que los procedimientos hay que mapearlos a mano, los delete en cascada siempre dan problemas al crearse… esto te hace gastar un monton de tiempo en depuracion, cosa que nhibernate deberia ahorrar (tiempo), por otro lado todo se trabaja con objetos… hasta las claves foraneas… ojala no tengas un valor de base de datos que sea not null por que solo se cae sin avisar exactamente el error si tienes algun campo asi y va algun null… y olvidense del limite de datos que tiene, si rescatan mas de 1000 filas de una tabla con muchas filas en una consulta… tampoco pueden mapearlo facilmente para reporting services y hacer informes con ello.
conclusion… pesima herramienta, que en vez de hacer tu desarrollo mas facil, lo hace mas lento y dificil.
Pingback: Eclipse y Tomcat
De todos los anteriores posts, me quedo con el de EDS_jorge, que con una sola pregunta daba en el clavo: «¿Alguien puede darme alguna ventaja real del uso de Hibernate sobre JDBC?».
Con mi experiencia puedo decir que a mí nada más que me ha aportado problemas. No digo que no hayan aplicaciones gigantescas, que tiren de más de una BBDD, que requieran «todo eso» que aporta el framework. Pero la verdad es que me han impuesto usarlo en un proyecto que a priori parecía bastante simple (una web con Struts, Spring e Hibernate) y no vean la lata que nos ha dado.
Básicamente dejamos de usar el conocido JDBC (qué no sé por qué lo pintan de complejo… ¿?… te conectas a la BBDD y haces las consultas. Nada más, con transacciones o sin ellas) para usar un desconocido Hibernate. A la larga nos dimos cuenta de que a veces el framework toma sus propias decisiones en cuando a modificar las consultas, o según el tipo de relación, a hacer guardados automáticos de los objetos. Una verdadera pena.
Obviamente no soy un experto en Hibernate, pero sólo quiero decir que ni JDBC es tan malo malísimo, ni Hibernate es la panacea!
Saludos.
gjisrngjkfm
gjisrngjkfm
khgdk
Muy bueno aclare muchas dudas que tenia =D
Gracias amigo!!
como saco una consulta de dos tablas y las meto en un objeto que no sea el .class de la tabla que se define si no en otro diferente ya que cuando ejecuto la consulta y le paso la lista al objeto no me trae los metadata y no los relaciona correctamente con el objeto
Muchas Gracias, súper util y aclarativo
alguien tiene un demo de hibernate con sql , aun estoy en la universidad y aun no me corre el mapeo quisiera ayuda por favor!
Grasias por la info me es de mucha utilidad
Hola pues antes que nada, quisiera conocer a profundidad sobre hibernate, debido a que estoy haciendo mi tesis, y lo requiero, alguien me podria decir de acuerdo a su experiencia las ventajas y desventajas, y los posibles errores que puede generar el relacionar Java con Postgres.
Espero sus respuestas…
un saludo para todos
que esten bien…
saludos
xao
Ando trabajando con hibernate y en particular me gusta trabajar con ¨criteria¨, pero me ha surgido una duda, que sucederá al ejecutar una criteria la cual espere como valor un string y esta sea una cosulta, ¿se ejecutará la cunsulta?
buen resumen, gracias.
Me gusto mas el tutorial para empezar struts, lo hace mas paso a paso, podrias poner como integro Hibernate a partir del otro tutorial??
Los que tenian el problema de [Ljava.lang.Object; cannot be cast to … ya lo pudieron resolver???, tengo el mismo problema, lo raro es que si puedo insertar asi que supongo que el mapping esta bien. Alguien Help!!!! =(
Me fue muy util tu explicacion para aclarar unos conceptos sobre hibernate q no los tenia bien claros…
Te felicito, muy bien explicado