Definitivo_hibernate_dia2.pdf

35
Mapeando relaciones y colecciones en hibernate Diciembre 2008 Diciembre 2008 Mapeando relaciones y colecciones en hibernate Diciembre 2008 Diciembre 2008 José A. García [email protected] José A. García [email protected]

Transcript of Definitivo_hibernate_dia2.pdf

Mapeando relaciones y colecciones en hibernateDiciembre 2008Diciembre 2008

Mapeando relaciones y colecciones en hibernateDiciembre 2008Diciembre 2008

José A. García [email protected]é A. García [email protected]

2

El Jueves vimos..

• Como configurar el entorno de hibernate

• Como realizar el mapeo de tipos básicos

• Como configurar un generador básico

• Como persistir una clase java simple usando hibernate

3

Más sobre valuetypes

• El desafío 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 estándar de la JDK) ya incluidos e incluso permite crear tipos nuevos.

4

Más sobre valuetypes

5

Más sobre valuetypes

6

Mapeo de grandes bloques de datos

Cuando queremos almacenar una gran cantidad de información generalmente recurricumos a tipos especiales en la BBDD.

Por ejemplo Mysql y Sqlserver proveen el tipo TEXT para almacenar textos grandes (de varias páginas).

Oracle Express incorpora los tipos CLOB y BLOB para almacenar textos y binarios de hasta 4GB.

Hibernate soporta también esos tipos especiales:

Generadores de identificadores

En el ejemplo que hicimos el último dia hemos visto los generadores “native” en HB3 existen algunos tipos más de generadores:

Generadores de identificadores

En el ejemplo que hicimos el último dia hemos visto los generadores “native” en HB3 existen algunos tipos más 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 opción sería hacer que el trigger se ejecutara solo en caso de conflictos y hacer que hibernate tome directamente la secuencia.

Ejercicios básicos

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 solución para el problema anterior (pequeña modif. en trigger).

Ejercicios básicos

create or replace trigger "BI_LIBROS" before insert on "LIBROS"for each row

declarecurr "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)) THENselect "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 través 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>

14

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;}

}

15

Vimos como persistir un mensaje

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

• Usamos hibernate para persistir los datos a la BBDDSession session = getSessionFactory().openSession();Transaction tx = session.beginTransaction();Message message = new Message("Hello World");session.save(message);tx.commit();session.close();

16

En la base de datos …

• El Código de traduce a

insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)

values (1, 'Hello World', null)

17

Para recrear el objeto haríamos

• 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();

18

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();

19

En la Base de Datos ..

• se traduciría a:

select m.MESSAGE_ID, m.MESSAGE_TEXT,m.NEXT_MESSAGE_IDfrom MESSAGES morder by m.MESSAGE_TEXT asc

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

20

Ejercicio 2 (basico)

Crea la tabla mensaje y su correspondiente secuencia. Inserta algunas filas y obten el mapeo de hibernate. Escribe el siguiente código:

Session session = getSessionFactory().openSession();Transaction tx = session.beginTransaction();// La fila 1 debe existirMessage 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();

21

Ejercicio 2 (basico)

¿Que acabamos de hacer? ¿Cuantas sentencias SQL ha lanzado Hibernate?

Ojea el fichero de mapeo, donde estan las relaciones foráneas? Veremos con mas detalle el mapeo de asociaciones mañana.

Modificar la tabla para que el texto se almacene en una columna clob de Oracle.

Recordemos las diferencias entre MR y MOONO SE CONSIDERAN LAS CLASES NO PERSISTENTES

Recordemos las diferencias entre MR y MOO

NO SE CONSIDERAN LAS RELACIONES NO ESTRUCTURALESp.e: administrativo GENERA informes

Recordemos las diferencias entre MR y MOO

NO EXISTE LA HERENCIA: se originan entidades débiles o especializaciones con discriminante

COPIA SECRETARIO GERENTE COMERCIAL

Nombre

Código

Docente

Categoría

Departamento

Administrativo

NombreCódigo

ÁreaDocente

Departamento ÁreaCategoría

Trabajador

Código Nombre

Administrativo

ES

• Representación de la generalizaciónMétodo 1:1. Crear una tabla para el {} de entidades de nivel más

alto (atributos claves: a1, a2, …, am )2. Crear una tabla para cada {} de entidades de nivel

más bajo (Atributos: b1, b2, …, bn)• Con: {b1, b2, …, bn} {a1, a2, …, am} columnas

Persona (nombre, calle ciudad)Empleado (nombre, sueldo)Cliente ( nombre, límite _crédito)

Representación de la generalización en MR

• Representación de la generalizaciónMétodo 2: (si es disjunta y completa)1. Crea una tabla para cada entidad del {} de entidades

de nivel más 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 más alto

Empleado (nombre, calle, ciudad, sueldo, idpersona)Cliente ( nombre, calle, ciudad, límite _crédito, idpersona)Persona (id, nombre, calle, ciudad, tipo)

Representación de la generalización en MR

28

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

29

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 crédito, efectivo y cheque respectivamente). El mapeo de "una tabla por jerarquía" se vería así:

30

una única tabla para toda la jerarquia de clases

31

Basada en una tabla por cada subclase concreta

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

32

Basada en una tabla por cada subclase concreta

33

Basada en una tabla por cada subclase concreta y un discriminante

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

34

Basada en una tabla por cada subclase concreta y un discriminante

35

Ejercicio

• Supongamos las clases:

– Mensaje Leido

•Guardan además del texto del mensaje, el nombre del lector y la fecha de la transcripción.

– Mensaje Multimedia

•Pueden guardar además 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