Está en la página 1de 10

HIBERNATE 3

Lo primero que hay que hacer es crear una tabla para realizar nuestros ejercicios, que tendrá
las siguientes características:

1 CREATE TABLE directores


2 (
3 NOMBRE VARCHAR(30) NOT NULL PRIMARY KEY,
4 EDAD INT
5 );

Despues crearemos un proyecto del tipo Aplicacion Java en el NetBeans y crearemos los
paquetes, que tendrán la siguiente estructura:

Como notara el lector hay un archivo llamado hibérnate.cfg.xml, este archivo contiene toda la
configuración de la conexión de la base de datos, es muy importante destacar que este
archivo se localiza en el paquete predeterminado del proyecto o en su defecto ver como esta
estructurado el proyecto en el disco duro en la carpeta src, ya que Hibernate es la ruta que
utiliza para encontrar dicho archivo a continuación mostraremos como esta estructurado
dicho archivo:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
3 <hibernate-configuration>
4 <session-factory>
5 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
6 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
7 <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/EMPRESA</property>
8 <property name="hibernate.connection.username">root</property>
9 <property name="hibernate.connection.password">admin</property>
10 <property name="hibernate.show_sql">true</property>
11 <property name="hibernate.hbm2ddl.auto">create</property>
12 <mapping resource="com/hibernate/mapeo/Maestro.hbm.xml"/>
13 </session-factory>
14 </hibernate-configuration>

La linea 5 indica el lenguaje SQL para cada tipo de gestor de Base de Datos ya sea,
MySQL, PostgreSQL, Oracle, Sybase etc, en nuestro caso usaremos MySQLDialect.

Las líneas 6-9 configuran el driver a cargar, la url de la Base de Datos, el usuario y el pass.

La línea 10 nos indica que los logs que genere Hibernate se mostraran por la consola, por
conveniencia siempre hay que ponerlo con valor true.

La linea 11 define la propiedad hibernate.hbm2ddl.auto, dicha propiedad lo que hace es que


cada vez que ejecutamos nuestra aplicación hibérnate resetea nuestra tabla borra, crea,
actualiza los registros existentes de la tabla.

La línea 12 indica donde se encuentran los archivos de mapeo, estos es la relación que
existe entre la base de datos y el bean.

RDBMS DIALECTO RDBMS DIALECTO


DB2 AS/400 org.hibernate.dialect.DB2400Dialect Microsoft SQL Server org.hibernate.dialect.SQLServerDi
alect
DB2 OS390 org.hibernate.dialect.DB2390Dialect SAP DB org.hibernate.dialect.SAPDBDialec
t
PostgreSQL org.hibernate.dialect.PostgreSQLDialect Informix org.hibernate.dialect.InformixDial
ect
MySQL org.hibernate.dialect.MySQLDialect HypersonicSQL org.hibernate.dialect.HSQLDialect
MySQL (InnoDB) org.hibernate.dialect.MySQLInnoDBDiale Ingres org.hibernate.dialect.IngresDialect
ct
MySQL ( MyISAM) org.hibernate.dialect.MySQLMyISAMDial Progress org.hibernate.dialect.ProgressDial
ect ect
Oracle(X version) org.hibernate.dialect.OracleDialect Mckoi SQL org.hibernate.dialect.MckoiDialect
Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect Interbase org.hibernate.dialect.InterbaseDial
ect
Sybase org.hibernate.dialect.SybaseDialect Pointbase org.hibernate.dialect.PointbaseDia
lect
Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDi FrontBase org.hibernate.dialect.FrontbaseDi
alect alect
DB2 org.hibernate.dialect.DB2Dialect Firebird org.hibernate.dialect.FirebirdDiale
ct

Ahora vamos a crear nuestro bean Director.java el cual va a tener tantas propiedades como
tenga columnas la tabla que queramos mapear, asi que serán 2 propiedades.
1 package com.hibernate.beans;
2 import java.io.Serializable;
3 public class Director implements Serializable
4 { //Propiedades del bean
5 private String nombreDirector;
6 private int edad;
7 //Constructor necesario para Hibernate
8 public Director()
9 { }
10 //métodos Getter y Setter
11 }

Una vez que tengamos nuestro bean vamos a crear nuestro archivo de mapeo
Director.hbm.xml, este archivo va ser el encargado de relacionar la tabla de la base de datos
con las propiedades del bean Director, se crearan 1 archivo por cada tabla que se requiera.

1 <?xml version="1.0" encoding="UTF-8"?>


2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4 <hibernate-mapping>
5 <class name="com.hibernate.beans.Director" table="directores">
6 <id column="NOMBRE" name="nombreDirector">
7 <generator class="assigned"/>
8 </id>
9 <property column="edad" name="edad"/>
10 </class>
11 </hibernate-mapping>

Todas las clases mapeadas para hibernate deben declarar la columna que será la llave
primaria en la tabla de la base de datos. Asi como la columna con la propiedad del bean.

<id
name="nombrePropiedad"
type="tipoDatos"
column="nombreColumnaTabla"
unsaved-value="null|any|none|undefined|id_value"
access="field|property|ClassName">
<generator class=" assigned "/>
</id>
- name (opcional): El nombre que identifica a la propiedad
- type (opcional): El nombre que indica el tipo de datos de Hibernate
- column (opcional, valor por default es el nombre de la propiedad): El nombre de la columna de la llave
primaria
- unsaved-value (opcional- valor por default es "sensible"): Indica que una instancia se vuelve a instanciar
diferenciandose con las otras instancias por separado que ya fueron actualizadas o cargadas en una
sesión previa.
- access (opcional - valor por default es property): El modo en que Hibernate accede a los valores de las
propiedades.

El tag <generator class=”assigned”> le indicamos que el id lo generamos nosotros y no Hibernate, en caso que
el id sea del tipo AUTO_INCREMENT seria la opción increment o identity.
Ahora vamos a crear la clase
HibernateUtil que es la que se
encarga de relacionar nuestro
archivo hibérnate.cfg.xml con
nuestro archivo de mapeo
Director.hbm.xml, el nombre de
esta clase puede ser cualquiera,
lo que pasa es que el NetBeans
nos da la opción de crearlo y es
asi como lo nombra
automáticamente cada vez que
lo crea, esta clase es la que nos
generara un Objeto del tipo
SessionFactory que sirve para
realizar nuestras operaciones
de cansulta, borrado, actualización e inserccion en nuestra base de datos.

1 package com.hibernate.session;
2 import org.hibernate.cfg.AnnotationConfiguration;
3 import org.hibernate.SessionFactory;
4 public class HibernateUtil
5 {
6 private static final SessionFactory sessionFactory;
7 static
8 {
9 try
10 {
11 // Obtenemos un objeto del tipo SessionFactory para que después este objeto crea uno del tipo Session
12 sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
13 }
14 catch (Throwable ex)
15 {
16 System.err.println("Initial SessionFactory creation failed." + ex);
17 throw new ExceptionInInitializerError(ex);
18 }
19 }
20
21 public static SessionFactory getSessionFactory()
22 {
23 return sessionFactory;
24 }
25 }//Fin de la clase HibernateUtil
Vamos a crear nuestra clase Main que será la que hara las pruebas de inserccion en nuestra
base de datos.

1 package com.hibernate.main;
2 import com.hibernate.beans.Director;
3 import com.hibernate.session.HibernateUtil;
4 import org.hibernate.HibernateException;
5 import org.hibernate.Session;
6
7 public class Main
8 {
9 private Session session;
10
11 public void prueba() throws HibernateException
12 { //Declaramos objetos Director
13 Director a = new Director();
14 a.setNombreDirector("Terry");
15 a.setEdad(23);
16 Director b = new Director();
17 b.setNombreDirector("Bruce");
18 b.setEdad(20);
19
20 session = HibernateUtil.getSessionFactory().openSession(); //Obtenemos la Session
21 session.beginTransaction(); //Es necesario empezar la Transaccion de lo contrario no guarda los objetos
22 session.save(a); //Guarda el Objeto a
23 session.save(b); //Guarda el Objeto b
24 session.getTransaction().commit(); //Finaliza la Transaccion
25 session.close(); //Cierra la Session
26 }
27
28 public static void main(String[] args)
29 {
30 Main prueba = new Main();
31 prueba.prueba();
32 }
33 }

Como podra observar el lector no se


necesito realizar consultas SQL para
insertar en la tabla, en vez de realizar
un INSERT INTO directores VALUES
(‘TERRY’,20); Se guardo un objeto en
la tabla.
Otra forma de mapear nuestras tablas es el uso de las anotaciones, ya que nos ahorra
tiempo, imaginese que tiene 100 tablas, para mapear tendrían que hacer 100 beans con su
repectivo archivo beans.hbm.xml dando un total de 200 archivos y declarar 100 de mas en
nuestro archivo hibérnate.cfg.xml.
El uso de las anotaciones nos ahorra los 100 archivos, los beans.hnm.xml.
Ejemplo para mapear nuestro bean Director será el siguiente:

1 package com.hibernate.beans;
2 import java.io.Serializable;
3 Import javax.persistence.Entity;
4 Import javax.persistence.Table;
5 Import javax.persistence.Id;
6 Import javax.persistence.Column;
7 //Es necesario antes de declara el bean que sea una entidad y que tabla se va a mapear
8 @Entity
9 @Table(name="directores")
10 public class Director implements Serializable
11 {
12 //Declaramos que propiedad del bean es el id
13 @Id
14 private String nombreDirector;
15 //Relacionamos la columna de la tabla con la propiedad del vean
16 @Column(name="nombre")
17 private int edad;
18
19 //Constructor necesario para Hibernate
20 public Director()
21 { }
22 //métodos Getter y Setter
23 }

Relaciones Uno a Uno Unidireccionales.

En las relaciones uno a uno un objeto entidad de una clase A está relacionado con uno y solo
un objeto entidad de una clase B. Si la relación es unidireccional solo el objeto A está
consciente de la relación (El objeto A tiene una referencia al objeto B) y el objeto B NO sabe
nada de esta. Por ejemplo, cuando tenemos una relación Persona -> Direccion (es uno a uno
porque una Persona, en teoría, solo puede tener una Direccion). Donde la Persona es la
entidad "A" y la Direccion es la entidad "B". O sea, la Persona conoce su Direccion pero la
Direccion no conoce a la Persona a la que pertenece.

En las relaciones bidireccionales las dos


entidades están conscientes de la
relación. Por ejemplo, si tenemos una
relación Pais <-> Presidente (es uno a uno
porque un Pais solo debería tener un
Presidente y un Presidente solo puede
serlo de un Pais). En este caso ambos
lados de la relación conocen el otro lado, o su "inverso". Para este ejemplo vamos a crear las
tablas Persona y Direccion:

Una vez definidas nuestras tablas, vamos a ver como configurar sus beans asi como sus
respectivos archivos de mapeo o usar las anotaciones en los propios beans.
1 /*TABLA DIRECCION*/
2 CREATE TABLE direccion
3 (
4 id bigint(20) NOT NULL AUTO_INCREMENT,
5 calle VARCHAR(255) DEFAULT NULL,
6 codigoPostal VARCHAR(255) DEFAULT NULL,
7 PRIMARY KEY (id)
8 );
1 /*TABLA PERSONAS*/
2 CREATE TABLE persona (
3 id bigint(20) NOT NULL AUTO_INCREMENT,
4 nombre varchar(255) DEFAULT NULL,
5 direccion_id bigint(20) DEFAULT NULL,
6 PRIMARY KEY (id),
7 FOREIGN KEY (direccion_id)
8 REFERENCES direccion (id) ); Notara el lector que se omitieron las
anotaciones @Table, @Column, ya que le estamos diciendo a Hibernate que el creara las
tablas por nosotros, los scripts anteriores muestran la configuración que uso Hibernate para
crear las tablas, en el ejemplo anterior, pusimos las anotaciones porque ya teníamos una
tabla definida, asi como asociamos cada propiedad del bean con nuestra tabla, observara
también que el nombre de la columnas de nuestras tablas es exactamente a las propiedades
del bean, y en el ejemplo anterior tuvimos que asociarlas explicitamente.

1 package hibernate.relaciones.beans;
2
3 import java.io.Serializable;
4 import javax.persistence.Entity;
5 import javax.persistence.GeneratedValue;
6 import javax.persistence.GenerationType;
7 import javax.persistence.Id;
8
9 @Entity
10 public class Direccion implements Serializable
11 {
12 private static final long serialVersionUID = 1962193842460657807L;
13 @Id
14 @GeneratedValue(strategy = GenerationType.IDENTITY)
15 private long id;
16 private String calle;
17 private String codigoPostal;
18
19 public Direccion()
20 {
21 }
22 //métodos Getter y Setter
23 }

1 package hibernate.relaciones.beans;
2
3 import java.io.Serializable;
4 import javax.persistence.CascadeType;
5 import javax.persistence.Entity;
6 import javax.persistence.GeneratedValue;
7 import javax.persistence.GenerationType;
8 import javax.persistence.Id;
9 import javax.persistence.OneToOne;
10
11 @Entity
12 public class Persona implements Serializable
13 { private static final long serialVersionUID = 2801192076668490052L;
14 @Id
15 @GeneratedValue(strategy = GenerationType.IDENTITY)
16 private long id;
17 private String nombre;
18 @OneToOne(cascade =
19 {
20 CascadeType.PERSIST, CascadeType.REMOVE
21 })
22 private Direccion direccion;
23 public Persona(){} //Construtor
24 //métodos getter y setter
25 }

La clase "Persona" se anota casi de la misma forma, con excepción de la indicación de la


relación uno a uno con la clase "Direccion". Para cada una de los 4 tipos de relaciones que
expliqué antes existe una anotación especial. En el caso de las relaciones uno a uno se usa
la anotación "@OneToOne" indicando cuál atributo representa la relación. En este caso la
relación está representado por el atributo "direccion".
Habiamos dicho que nos interesa que cuando guardamos y eliminamos la "Persona" también
se elimine la "Direccion" asociada, y que esto se logra indicando que esas operaciones se
hagan en cascada. Usando anotaciones también podemos indicar eso usando el atributo
"cascade" de la anotación que representa la relación (en este caso "@OneToOne"). Este
atributo recibe un arreglo de objetos tipo "javax.persistence.CascadeType" la cual es una
enumeración. Cada elemento de la enumeración representa una operación que será
realizada en cascada. Usando las anotaciones de JPA tenemos un número menor de
operaciones que con los archivos de mapeo. De hecho solo tenemos: merge, persist,
refresh, remove, all. Por default ninguna operación se realiza en cascada, pero nosotros
queremos que se realicen en cascada las operaciones de guardar y eliminar, por lo que
colocamos estos valores de la siguiente forma:

@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
private Direccion direccion;
Además, y para terminar con esta parte, había comentado que Hibernate realizará las
operaciones en cascada suponiendo que tanto la Persona como la Direccion tienen el mismo
identificador, pero que esto podría no siempre ser verdad (como en el ejemplo que vimos
anteriormente). Por lo que debemos indicar que el identificador de Persona debe ser el
mismo que el de Direccion. Para indicar esto con anotaciones se supone que usamos la
anotación "@PrimaryKeyJoinColumn" en el elemento del que se tomará el id, que en ese
caso también es "direccion", pero en la práctica esto no funciona, de hecho hay muchos
reportes en el sitio de Hibernate indicando esto. Así que dejamos la anotación de la relación
como está. Con esto lograremos que en la tabla en la que se almacene las entidades
"Persona" se agregue una columna más para indicar con cuál "Direccion" está relacionada.

Ahora veremos como configurar nuestros beans por archivos de mapeo, asumiramos que los
beans tienen los mismos atributos y métodos, quitando las anotaciones de los ejemplos
anteriores.El mapeo de la clase "Dirección" es muy simple, y queda de la siguiente forma:

1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4 <hibernate-mapping>
5 <class name="hibernate.relaciones.modelo.Direccion" table="DIRECCIONES">
6 <id name="id" column="ID">
7 <generator class="identity" />
8 </id>
9 <property name="calle" />
10 <property name="codigoPostal" />
11 </class>
12 </hibernate-mapping>
Ahora crearemos el mapeo de la clase "Persona", en un archivo llamado llamado
"Persona.hbm.xml" en el paquete "mapeos", la cuál de hecho será muy parecido al de
"Direccion", excepto en el identificador. Queremos que el identificador de la "Persona" y de la
"Direccion" sean el mismo, ya que en las relaciones uno a uno Hibernate supone que ambas
entidades tendrán el mismo identificador (lo cual podría no siempre ser verdad) y de esta
forma la recuperación de la Direccion se hará automáticamente al momento de recuperar la
Persona, lo mismo ocurre con la eliminación. Pero como solamente Persona está consciente
de la relación, es ella quien recibirá el mismo identificador que la Direccion.Para lograr esto
usamos un generador especial de id llamado "foreign", indicando que el identificador será
tomado de otra entidad. Decimos que la entidad está referenciada como la propiedad
"direccion" de nuestra clase "Persona". Por lo que el identificador queda así:

1 <hibernate-mapping>
2 <class name="hibernate.relaciones.modelo.Persona" table="PERSONAS">
3 <id name="id" column="ID">
4 <generator class="foreign">
5 <param name="property">direccion</param>
6 </generator>
7 </id>
8
9 <property name="nombre" />
10
11 <one-to-one name="direccion" cascade="persist, delete"/>
12 </class>
13 </hibernate-mapping>

También podría gustarte