Definitivo_hibernate_dia1

Page 1

Introducción a hibernate Diciembre 2008

José A. García jagarcia@siteframe.tk


Dos mundos distintos • Hoy en día, la práctica totalidad de los lenguajes de programación que surgen son orientados a objetos y esta tecnología se ha convertido en el estándar actual de programación que, a su vez, está generando nuevos desarrollos muy prometedores para el futuro (como, por ejemplo, la programación orientada a aspectos).


Dos mundos distintos • La programación orientada a objetos intenta modelar estos objetos reales con estructuras de programa, llamadas “objetos de software” o, simplemente, “objetos”. Cada uno de estos objetos de software, está compuesto por una serie de características (llamadas “atributos”) y una serie de acciones (llamadas “métodos”).

• Si nuestros coches incluyen piezas tenemos una agregación de objetos


Dos mundos distintos • El modelo relacional es muy diferente del modelo orientado a objetos. Por una parte, el modelo relacional sólo se ocupa de la parte estática de la aplicación (de los “datos”) y no de la parte dinámica (“los procesos”). • Hay otra gran diferencia entre ambos, la forma en la que el modelo relacional trata los datos es muy diferente a cómo lo hace el modelo orientado a objetos. Mientras en este último, los datos son modelados en forma de objetos, en el modelo relacional son modelados como registros planos.


Incompatibilidades entre OO y MR • El problema aparece cuando intentamos traducir objetos a tablas relacionales. – Granularidad – Subtipos – Identidad – Asociaciones direccionales …

March 12, 2009

5


Problema de la Granularidad • Los objetos en OO son multidimensionales • En SQL los tipos y las relaciones entre tablas son planas y hay un escaso soporte para tipos definidos por el usuario. • Esto fuerza a los desarrolladores a usar estructuras menos flexibles en el modelo de objetos.

March 12, 2009

6


Problema de los Subtipos • Los objetos java soportan herencia (super & sub clases). • Cada sub o super clase puede definir datos distintivos y funcionalidad diferente. • Un objeto puede ser asociado con objetos de diferentes clases pero del mismo tipo (polimorfismo). • SQL no soporta relaciones de herencia ni polimorfismo.

March 12, 2009

7


Problema de la Identidad • Comprobar si dos objetos son iguales • Java define dos notaciones: •Identidad de objetos [==] •Equivalencia de valor [.equals()] • Para SQL dos registros son el mismo si contienen la misma clave primaria. • Dos o más objetos pueden representar la misma fila (registro) en la BBDD.

March 12, 2009

8


Problema de las Asociaciones • Las asociaciones relacionan entidades. • En Java una referencia a un objeto representa una asociacion. • En SQL una asociacion esta representada por una foreign key. • Las referencias a objetos son direccionales las FK no.

March 12, 2009

9


Diferencias en la navegación • Los objetos son accedidos de forma totalmente diferente en Java y en SQL obj.getDetails().getFirstField() • En SQL estos detalles se obtendrian a través de uno o varios join.

March 12, 2009

10


El coste de estas diferencias • Requieren un esfuerzo y un tiempo considerable • Alrededor 30-40% del esfuerzo se dedica a operaciones tediosas de SQL/JDBC

March 12, 2009

11


Object/relational Mapping (ORM) • La solución es la misma que se daría en la vida real. Se debe encontrar un traductor que sepa traducir de cada idioma al otro. De esta forma, las dos personas se entenderán sin necesidad de que uno hable el idioma del otro. En el mundo de la programación este traductor no es más que un componente de software (concretamente, una capa de programación), al que se le dan los nombres de “capa de persistencia”, “capa de datos”, “correspondencia O/R” (“OR mapping”) o “motor de persistencia”. • Nosotros veremos Hibernate ORM.


Object/relational Mapping (ORM) • Para rescatarnos de tanta tediosidad aparecen los ORM. • Un ORM es una herramienta que permite automatizar la mayor parte del acceso no critico a la BBDD, persistiendo los objetos de forma automática y transparente.

March 12, 2009

13


Tipos de ORM

1. Puramente relacional • •

Generan el modelo de objetos equivalente al modelo relacional Desaprovechan las ventajas OO, y son dificilmente portables.

2. Mapeo ligero • •

Utilizan SQL/JDBC para crear soluciones de mapeo a medida Esta solución continua siendo muy popular

3. Mapeo básico •

Son capaces de generar el código relacional en tiempo de ejecución para los casos mas simples

4. Mapeo avanzado •

Soportan modelado de caracteríscas sofisticadas como: composicion, herencia, polimorfismo & persistencia.

– Hibernate es un ORM de tipo 4. March 12, 2009

14


Pero que nos aporta realmente Hibernate sobre JDBC? • PROGRAMACIÓN MAS LIMPIA. Con jdbc el código de bbdd se entremezcla con el resto. Hibernate nos provee una capa de abstracción con la bbdd y una capa de persistencia perfectamente aisladas. • INDEPENDENCIA DE LA BBDD PERO TAMBIEN DE SU DIALECTO • CONTROL DE TRANSACCIONES mediante JTA. • CONVERSION Y VALIDACION de tipos automática. March 12, 2009

15


Pero que nos aporta realmente Hibernate sobre JDBC? • INTEGRACION PERFECTA CON XDOCLET y anotaciones de JDK 5. • Mapeo avanzado de asociaciones.

March 12, 2009

16


Ventajas de usar ORM • Esta solución goza de las mejores ventajas de los dos modelos: – Por una parte, podemos programar con orientación a objetos, aprovechando las ventajas de flexibilidad, mantenimiento y reusabilidad. – Por otra parte, podemos usar una base de datos relacional, aprovechándonos de su madurez y su estandarización así como de las herramientas relacionales que hay para ella.

• Se calcula que un motor de persistencia puede reducir el código de una aplicación en un 40%, haciéndola menos costosa de desarrollar. Además, el código que se obtiene programando de esta manera es más limpio y sencillo y, por lo tanto, más fácil de mantener y más robusto.


Primera clase con hibernate


Primera clase con hibernate

La estructura de Bean es muy importante para hibernate ya que la capa de persistencia autoinstanciarĂĄ las clases y no podrĂ­a hacerlo si no proveemos un constructor vacio. Hibernate reconoce los mĂŠtodos standart SET, GET, IS..


El archivo de mapeo Hibernate necesita saber c贸mo cargar y almacenar objetos de la clase persistente. Aqu铆 es donde entra en juego el archivo de mapeo. Un archivo de mapeo es un archivo XML que cumple con el DTD de los archivos de mapeo de hibernate. Este DTD es complicado por lo que lo iremos viendo poco a poco.


El archivo de mapeo Para nuestro ejemplo el fichero de mapeo podría ser:

La etiqueta CLASS es la mas importante porque define la tabla de la bd donde se persisten los objetos La etiqueta ID define el mapeo del identificador único a la clave primaria de la tabla. La etiqueta GENERATOR indica una estrategia de generación automática. En este caso de tipo “nativo”.


El archivo de mapeo Para nuestro ejemplo el fichero de mapeo podría ser:

La etiqueta PROPERTY declara una propiedad persistente. POR DEFECTO TODAS LAS PROPIEDADES DE LA CLASE SON NO PERSISTENTES. El atributo name declara el nombre de la propiedad java. Hibernate usará ese nombre para acceder a Los métodos GET/SET correspondientes.


El archivo de mapeo Para nuestro ejemplo el fichero de mapeo podría ser:

¿Por qué el mapeo de la propiedad date incluye el atributo column pero el de title no? ¿Por qué el mapeo de title no incluye type? Hibernate no puede decidir automaticamente si el tipo de la columna que proviene de un atributo Java.util.Date será Date ó Time ó Timestamp.


Configurar el entorno Para la configuración de Hibernate podemos usar un simple archivo hibernate.properties, un archivo hibernate.cfg.xml algo más complicado, o incluso una configuración totalmente en tiempo de ejecución. Probablemente la solución mas versatil sea el fichero xml. Para nuestro ejemplo el fichero cfg.xml podría ser:


Configurar el entorno

Lo primero que hay que darse cuenta es que este fichero tiene su propia DTD que tenemos que seguir. Configuramos la SessionFactory una fabrica global responsable de una base de datos en particular.


Configurar el entorno

La propiedad hibernate.dialect especifica la variante de SQL que hibernate generarรก para hablar con la BD. Al contrario que JDBC hibernate nos permite adaptarnos al dialecto hablado por la BD.


Configurar el entorno

La propiedad hibernate.current_session_context_class es muy importante porque define el comportamiento de las sesiones. En este caso la unidad de trabajo de hibernate queda ligada al thread de java que se este ejecutando en el momento de crearla. Veremos esto mas adelante.


Configurar el entorno

Por Ăşltimo declaramos los ficheros que contendrĂĄn los mapeos de los objetos en la BD.


HibernateUtil.java Llegados a este punto Hibernate es capaz de conectar con nuestra BBDD, manejar la conexiĂłn independientemente de que esta se obtenga a travĂŠs de JDBC o de otros mecanismos como JNDI, y escribir-leer objetos en ella. Lo Ăşnico que necesitamos es una clase que nos permita comunicarnos con hibernate para solicitarle operaciones. Esta clase es HibernateUtil.java

Lo que nos va a importar de hibernateUtil.java es que nos provee de una clase singleton capaz de crear un objeto SessionFactory de forma unica, mantenerlo de forma global y devolverlo de forma facil.


HibernateUtil.java Una implementación básica de HibernateUtil suele estar incluida en todos los entornos de desarrollo y en nuestro caso podría ser:


Comenzando a usar Hibernate Ya podemos usar Hibernate, nuestra primera prueba serรก salvar un evento. Simplemente hacemos:


Comenzando a usar Hibernate

Lo primero que hacemos es obtener la unidad de trabajo actual (CurrentSession) a trav茅s de HibernateUtil. Hemos asignado cada unidad de trabajo a un thread. Una sesi贸n comienza cuando se la necesita por primera vez, entonces queda ligada al thread actual. Si volvemos a llamar a getCurrentSession obtenemos la misma unidad de trabajo. Una vez que la transacci贸n termina Hibernate desliga la sesi贸n y la cierra automaticamente.


Comenzando a usar Hibernate

Una transacción en la BD siempre se inicia invocando al método beginTransaction() del objeto sesión y terminará bien en una confirmación, bien en una orden deshacer.


Comenzando a usar Hibernate Igual de fácil seria la recuperación de datos desde tablas (generación de objetos):

Lo que hicimos aquí, es usar el lenguaje de consultas de Hibernate (HQL, por sus siglas en inglés) para cargar todos los objetos Event que existen en la base de datos. Hibernate generará el código SQL que haga falta, lo enviará la base de datos, y poblará los objetos Event con los datos que sean devueltos. Se pueden crear consultas SQL mucho más complejas con HQL, por supuesto. Pero es importante que esto no es SQL sino HSQL, que veremos en detalle mas adelante.


Ejercicio inicial Crear un proyecto base en NetBeans integrando Hibernate.

hacer en clase


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

36


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

37


Otro Ejemplo โ ข El Cรณdigo de traduce a insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (1, 'Hello World', null)

38


Otro Ejemplo • Podemos recrear el Objeto así Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); List messages = newSession.find("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(); 39


Otro Ejemplo • Que se traduciría a: select m.MESSAGE_ID, m.MESSAGE_TEXT,m.NEXT_MESSAGE_ID from MESSAGES m order by m.MESSAGE_TEXT asc

40


Otro Ejemplo • Podemos Actualizar un mensaje haciendo: Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); // 1 is the generated id of the first message Message message = (Message) session.load( Message.class, new Long(1) ); message.setText("Greetings Earthling"); Message nextMessage = new Message("Take me to your leader (please)"); message.setNextMessage( nextMessage ); tx.commit(); session.close();

41


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.