Está en la página 1de 35

Mapeando relaciones y colecciones en hibernate

Diciembre 2008

Jos A. Garca jagarcia@siteframe.tk

El Jueves vimos..

Como configurar el entorno de hibernate Como realizar el mapeo de tipos bsicos Como configurar un generador bsico Como persistir una clase java simple usando hibernate

Ms sobre valuetypes

El desafo es mapear el sistema de tipos de Java a un sistema del tipo SQL/BD. El puente entre ambos sistemas es provisto por Hibernate. Para las entidades existen clases (<class>) y subclases (<subclass>). Para los "value types" usamos <property>, normalmente con un atributo type. El valor de este atributo es uno de los tipos para mapeo de Hibernate. Hibernate trae varios mapeos (para los tipos estndar de la JDK) ya incluidos e incluso permite crear tipos nuevos.
3

Ms sobre valuetypes

Ms sobre valuetypes

Mapeo de grandes bloques de datos


Cuando queremos almacenar una gran cantidad de informacin generalmente recurricumos a tipos especiales en la BBDD. Por ejemplo Mysql y Sqlserver proveen el tipo TEXT para almacenar textos grandes (de varias pginas). Oracle Express incorpora los tipos CLOB y BLOB para almacenar textos y binarios de hasta 4GB. Hibernate soporta tambin esos tipos especiales:

Generadores de identificadores
En el ejemplo que hicimos el ltimo dia hemos visto los generadores native en HB3 existen algunos tipos ms de generadores:

Generadores de identificadores
En el ejemplo que hicimos el ltimo dia hemos visto los generadores native en HB3 existen algunos tipos ms de generadores:

Generadores de identificadores
En Oracle XE una secuencia normalmente lleva asociado un trigger que realiza el reemplazo luego en este caso la mejor opcin sera hacer que el trigger se ejecutara solo en caso de conflictos y hacer que hibernate tome directamente la secuencia.

Ejercicios bsicos
Utilicemos la tabla Libros que creamos en la parte de Oracle o genera una nueva con su correspondiente pareja secuencia-trigger de reemplazo. Mapeemos la tabla con el asistente de netBeans. La tabla libros tenia un identificador nico id_libro que es PK en la tabla. Por defecto NB nos asocia un generador de tipo assigned . Qu ocurre si intentamos insertar un valor de ID que ya existe? Cambiar el tipo de generador a sequence. Intentar insertar un valor, que ocurre? Haz los cambios que consideres oportunos para evitar el error anterior. Haz varias inserciones. Que problema observas ahora? Plantea alguna solucin para el problema anterior (pequea modif. en trigger).

Ejercicios bsicos
create or replace trigger "BI_LIBROS" before insert on "LIBROS" for each row declare curr "LIBROS".ID%TYPE; exis NUMBER; begin select count(ID) into exis from "LIBROS" where ID=:NEW.ID; select "LIBROS_SEQ".currval into curr from dual; if ((:NEW.ID>curr+1) OR (exis>0)) THEN select "LIBROS_SEQ".nextval into :NEW.ID from dual; end if; end;

org.hibernate.id.enhanced.SequenceStyleGenerator
Las incompatibilidades entre diferentes BBDD a la hora de generar identificadores han llevado a que Hibernate incorpore sus propios generadores externos. Este es el caso del SequenceStyleGenerator. Lo que hace el SSG es simular el comportamiento de una secuencia implementandolo a travs de tablas en las BBDD que no soportan sequencias.

org.hibernate.id.enhanced.SequenceStyleGenerator
...... <id name="tid" type="java.lang.Long"> <column name="TID" precision="16" scale="0" /> <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"> <param name="sequence_name">LIBROS_SEQ</param> <param name="initial_value">1</param> <param name="increment_size">10</param> </generator> ....... </id>

Volvamos al ejemplo del Jueves


public class Message { private Long id; private String text; private Message nextMessage; private Message() {} public Message(String text) { this.text = text; } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Message getNextMessage() { return nextMessage; } public void setNextMessage(Message nextMessage) { this.nextMessage = nextMessage; } }

14

Vimos como persistir un mensaje


La clase mensaje puede ser usada como cualquier otra clase
Message message = new Message("Hello World"); System.out.println( message.getText() );

Usamos hibernate para persistir los datos a la BBDD


Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); Message message = new Message("Hello World"); session.save(message); tx.commit(); session.close();

15

En la base de datos
El Cdigo de traduce a
insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (1, 'Hello World', null)

16

Para recrear el objeto haramos newSession.load ( clase del objeto, idObj )


Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); Event loadedEvent = (Event)session.load(Event.class, e.getId()); System.out.println(loadedEvent.getName()); newTransaction.commit(); newSession.close();

17

Para ejecutar una query Session.CreateQuery (sentencia HSQL)


Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); List messages = newSession.createQuery("from Message as m order by m.text asc"); System.out.println( messages.size() + " message(s) found:" ); for ( Iterator iter = messages.iterator();iter.hasNext(); ) { Message message = (Message) iter.next(); System.out.println( message.getText() ); } newTransaction.commit(); newSession.close();

18

En la Base de Datos ..
se traducira a:
select m.MESSAGE_ID, m.MESSAGE_TEXT,m.NEXT_MESSAGE_ID from MESSAGES m order by m.MESSAGE_TEXT asc

NOTA: ES IMPORTANTE NOTAR LA DIFERENCIA ENTRE EL HSQL Y EL CODIGO SQL FINAL.

19

Ejercicio 2 (basico)
Crea la tabla mensaje y su correspondiente secuencia. Inserta algunas filas y obten el mapeo de hibernate. Escribe el siguiente cdigo:
Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); // La fila 1 debe existir Message message = (Message) session.load( Message.class, 1 ); message.setText(Hola mundo!); Message nextMessage = new Message(queda mucho por hacer); message.setNextMessage( nextMessage ); tx.commit(); session.close();
20

Ejercicio 2 (basico)
Que acabamos de hacer? Cuantas sentencias SQL ha lanzado Hibernate? Ojea el fichero de mapeo, donde estan las relaciones forneas? Veremos con mas detalle el mapeo de asociaciones maana. Modificar la tabla para que el texto se almacene en una columna clob de Oracle.

21

Recordemos las diferencias entre MR y MOO


NO SE CONSIDERAN LAS CLASES NO PERSISTENTES

Recordemos las diferencias entre MR y MOO

NO SE CONSIDERAN LAS RELACIONES NO ESTRUCTURALES p.e: administrativo GENERA informes

Recordemos las diferencias entre MR y MOO

NO EXISTE LA HERENCIA: se originan entidades dbiles o especializaciones con discriminante

COPIA

SECRETARIO

GERENTE

COMERCIAL

Categora

Nombre Cdigo Nombre

Docente
Cdigo Departamento

Trabajador
ES

rea

Docente Administrativo
Categora Cdigo Nombre Departamento

Administrativo

rea

Representacin de la generalizacin en MR
Representacin de la generalizacin Mtodo 1: 1. Crear una tabla para el {} de entidades de nivel ms alto (atributos claves: a1, a2, , am ) 2. Crear una tabla para cada {} de entidades de nivel ms bajo (Atributos: b1, b2, , bn) Con: {b1, b2, , bn} {a1, a2, , am} columnas Persona (nombre, calle ciudad) Empleado (nombre, sueldo) Cliente ( nombre, lmite _crdito)

Representacin de la generalizacin en MR
Representacin de la generalizacin Mtodo 2: (si es disjunta y completa) 1. Crea una tabla para cada entidad del {} de entidades de nivel ms alto con: {discriminante} {a1, a2, , am} columnas 2. se crean tablas secundarias para las entidades de nivel mas bajo incluyendo la clave de la tabla mas alta: {b1, b2, , bn}: atributos de la entidad {a1, a2, , am}: atributos clave de la entidad de nivel ms alto Empleado (nombre, calle, ciudad, sueldo, idpersona) Cliente ( nombre, calle, ciudad, lmite _crdito, idpersona) Persona (id, nombre, calle, ciudad, tipo)

Mapear relaciones de herencia en Hibernate

Hibernate define 3 estrategias para mapear herencia: - Basada en una nica tabla para toda la jerarquia de clases - Basada en una tabla por cada subclase concreta - Basada en una tabla por cada subclase y un discriminante

28

una nica tabla para toda la jerarquia de clases


Supongamos que tenemos una interfaz Payment (pago), implementada por las clases CreditCardPayment, CashPayment, ChequePayment (pago por tarjeta de crdito, efectivo y cheque respectivamente). El mapeo de "una tabla por jerarqua" se vera as:

29

una nica tabla para toda la jerarquia de clases

30

Basada en una tabla por cada subclase concreta


En este caso la herencia se implementa mediante un cruce (<joined-subclass>):

31

Basada en una tabla por cada subclase concreta

32

Basada en una tabla por cada subclase concreta y un discriminante


En este caso usamos juntos <subclass> y <join>:

33

Basada en una tabla por cada subclase concreta y un discriminante

34

Ejercicio
Supongamos las clases:
Mensaje Leido

Guardan adems del texto del mensaje, el nombre del lector y la fecha de la transcripcin.
Mensaje Multimedia

Pueden guardar adems del texto del mensaje un enlace a una imagen y una referencia a un fichero multimedia (musica,video..)
Definir las relaciones de herencia y su adecuado mapeo en Hibernate

35

También podría gustarte