Manual Hibernate Con Java
Manual Hibernate Con Java
Hibernate
14-1
14-2
Hibernate
Desarrolladores Java acostumbrados a trabajar con JDBC probablemente se pregunten cules son las razones para utilizar un ORM.
Introduccin a Hibernate
Introduccin
Hibernate es una herramienta ORM completa que ha conseguido en un tiempo record una excelente reputacin en la comunidad de desarrollo posicionndose claramente como el producto OpenSource lder en este campo gracias a sus prestaciones, buena documentacin y estabilidad. Es valorado por muchos incluso como solucin superior a productos comerciales dentro de su enfoque, siendo una muestra clara de su reputacin y soporte la reciente integracin dentro del grupo JBoss que seguramente generar iniciativas muy interesantes para el uso de Hibernate dentro de este servidor de aplicaciones. Se empez a desarrollar hace algo unos aos por Gavin King siendo hoy Gavin y Christian Bauer los principales gestores de su desarrollo. Hibernate parte de una filosofa de mapear objetos Java "normales", tambin conocidos en la comunidad como "POJOs" (Plain Old Java Objects), no contempla la posibilidad de automatizar directamente la persistencia de Entity Beans tipo BMP (es decir, generar automticamente este tipo de objetos), aunque an asi es posible combinar Hibernate con este tipo de beans utilizando los conocidos patrones para la delegacin de persistencia en POJOs. Una caracterstica de la filosofa de diseo de Hibernate ha de ser destacada especialmente, dada su gran importancia: puede utilizar los objetos Java definidos por el usuario tal cual, es decir, no utiliza tcnicas como generacin de cdigo a partir de descriptores del modelos de datos o manipulacin de bytecodes en tiempo de compilacin (tcnica conocida por su amplio uso en JDO), ni obliga a implementar
Hibernate
14-3
interfaces determinados, ni heredar de una superclase. Utiliza en vez de ello el mecanismo de reflexin de Java. Las razones que hacen que el uso de Hibernate sea muy importante son: Simplicidad y flexibilidad: necesita un nico fichero de configuracin en tiempo de ejecucin y un documento de mapeo para cada aplicacin. Este fichero puede ser el estndar de Java (extensin properties) o un fichero XML. Tambin se tiene la alternativa de realizar la configuracin de forma programtica. El uso de frameworks de persistencia, tales como EJBs hace que la aplicacin dependa del framework. Hibernate no crea esa dependencia adicional. Los objetos persistentes en la aplicacin no tienen que heredar de una clase de Hibernate u obedecer a una semntica especfica. Tampoco necesita un contenedor para funcionar. Completo: ofrece todas las caractersticas de orientacin a objetos, incluyendo la herencia, tipos de usuario y las colecciones. Adems, tambin proporciona una capa de abstraccin SQL llamada HQL. Las sentencias HQL son compiladas por el framework de Hibernate y cacheadas para su posible reutilizacin. Prestaciones: uno de las grandes confusiones que aparecen al utilizar este tipo de frameworks es creer que las prestaciones de la aplicacin se ven muy mermadas. Este no es el caso de Hibernate. La clave en este tipo de situaciones es si se realizan el nmero mnimo de consultas a la base de datos. Muchos frameworks de persistencia actualizan los datos de los objetos incluso cuando no ha cambiado su estado. Hibernate slo lo hace si el estado de los objetos ha cambiado. El cacheado de objetos juega un papel importante en la mejora de las prestaciones de la aplicacin. Hibernate acepta distintos productos de cacheado, tanto de cdigo libre como comercial.
14-4
Hibernate
Conceptos bsicos
Tipos de Objetos Hibernate distingue entre dos tipos de objetos: Transient: slo existen en memoria y no en un almacn de datos (recurdese en este sentido tambin el modificador transient de Java), en algunos casos, no sern almacenados jams en la base de datos y en otros es un estado en el que se encuentran hasta ser almacenados en ella. Los objetos transient han sido instanciados por el desarrollador sin haberlos almacenado mediante una sesin. Persistent: se caracterizan por haber sido ya almacenados y ser por tanto objetos persistentes. Han sido creados y almacenados en una sesin o bien devueltos en una consulta realizada con la sesin. Sesin Para almacenar y recuperar estos objetos de la base de datos, el desarrollador debe mantener una conversacin con el motor de Hibernate mediante un objeto especial, la sesin (clase Session). Sirve para delimitar una o varias operaciones relacionadas dentro de un proceso de negocio, demarcar una transaccin y aporta algunos servicios adicionales como una cach de objetos para evitar interacciones innecesarias contra la Base de Datos. Las sesiones son un concepto ligado a un proceso de negocio, por tanto es natural pensar que una sesin siempre va a pertener a un mismo thread de ejecucin (el que pertenece a la ejecucin de un mtodo de negocio para un usuario o sistema externo concreto), aunque tcnicamente se pueden compatir sesiones entre threads, esto no se debe hacer jams por no ser una buena poltica de diseo y los consecuentes problemas que puede generar.
Hibernate
14-5
En un entorno multiusuario y por tanto multithread habr por tanto mltiples sesiones simultneas, cada una perteneciente a su correspondientes threads y con su contexto de objetos en cach, transacciones, etc. Como tal no sorprende que las sesiones no son thread-safe y que la informacin vinculada a ella no sea visible para otras sesiones. Es tambin lgico que tenga que existir una institucin superior para crear sesiones y realizar operaciones comunes a los diferentes threads como lo puede ser la gestin de una cach compartida entre threads o cach de segundo nivel. Este elemento es la clase SessionFactory y en ella podremos encontrar mtodos como openSession() o evict(Class persistentClass).
14-6
Hibernate
Arquitectura Hibernate Se analiza la arquitectura de Hibernate desde un punto de vista muy general:
Hibernate utiliza la base de datos y los ficheros de configuracin para proporcionar servicios de persistencia a la aplicacin.
Hibernate
14-7
14-8
Hibernate
Entorno de desarrollo
Introduccin
El principal objetivo en esta captulo es conocer cules son los pasos a llevar a cabo para poder construir un proyecto con Hibernate. Para ello se deben realizar una serie de tareas generales: Obtener una distribucin de Hibernate: el primer paso para crear un proyecto con Hibernate ser obtener la ltima copia de Hibernate de su sitio web. Obtener Ant: (Java build tool) no es estrictamente necesaria pero no har la vida ms fcil. Configurar una base de datos.
Distribucin de Hibernate
Bibliotecas Hibernate HibernateExtensions Hibernate-lib Descripcin Clases de la API de Hibernate incluyendo la clase SchemaExportTask Las clases que forman la extensin de Hibernate incluyendo la clase Hbm2JavaTask. Clases de Hibernate auxiliares Ficheros JAR/Zip hibernate2.jar hibernate-tools.jar dom4j-1.4.jar commons-logging-1.0.4.jar commons-collections-2.1.1.jar ehcache-0.9.jar cglib-full-2.0.2.jar jta.jar
Hibernate
14-9
Ant
Ant es una herramienta del tipo de make (gnumake, nmake...) cdigo abierto. Fu desarrollada dentro del Proyecto Apache Jakarta(http://jakarta.apache.org/ant) en Java. Utiliza ficheros de configuracin XML. Para ejecutar Ant en lnea de comandos se utiliza el comando ant:
14-10
Hibernate
Por defecto busca el fichero build.xml en el directorio actual. -find busca build.xml en el directorio padre y siguientes hasta el raz. -buildfile filename para indicar otro fichero. Se pueden especificar uno o ms targetsa ejecutar. Por defecto ejecuta el targetindicado en el atributo default de la etiqueta <project>. Ej: ant buildfile test.xml compile Se pueden establecer propiedades que sobreescribana las especificadas en el buildfile. -Dproperty=value Variables de entorno:ant-DMYVAR=$MYVAR ... Otras opciones: -help, -version, -quiet, -verbose, -projecthelp, -listener... Los buildfiles son ficheros con formato xml que almacenan informacin de un determinado proyecto. Se disean para realizar una serie de acciones sobre el proyecto (targets). Etiqueta <project>: <name>: nombre del proyecto. <default>: target por defecto <basedir>: directorio base. Etiqueta <target>: es un objetivo compuesto por varias tareas que se ejecutan secuencialmente cuando se ejecuta el target. <name>: nombre del target, obligatorio <depends>: lista de targets de los cuales depende.
Hibernate
14-11
<if> / <unless> <description> Cada tarea a realizar en Ant est implementada en una clase Java: Hay un conjunto de tareas incluidas en Antt, otras en .jar opcionales y, adems, es posible incluir tareas propias. Algunas de esas tareas son: Ant: Llama a una target de otro buildfile. Copy: Copia ficheros y directorios. Delete: Borra ficheros y directorios. Echo: Enva un mensaje a System.out o a fichero. GZip: Crea un fichero Gzip. Javac: Compila cdigo fuente Java. Javadoc: Genera ficheros HTML javadoc. Mkdir: Crea un directorio y todos los directorios padre necesarios. Property: Permite establecer valores de propiedades. Tar: Crea un fichero TAR a partir de un conjunto de ficheros. Se muestra a continuacin un ejemplo de fichero build.xml:
<?xml version="1.0"?> <project name="HibernateJSF" default="schemaGenerator"> <!-Definicin de propiedades de sistema --> <property name="dirFuente" value="src"/> <property name="dirEjecutable" value="classes"/> <property name="hibernate" value="hibernate-2.1"/>
14-12
Hibernate
<property name="hibernate.mappings" value="mappings"/> <!--<property name="jdbc" value="C:\oracle\product\10.1.0\Db_1\jdbc"/> --> <property name="hibernate.extensions" value="tools"/> <property name="hibernate.properties" value="properties"/> <!-Rutas que se van a utilizar dentro de nuestras tareas --> <path id="project.class.path"> <pathelement location="${dirEjecutable}" /> <!-- Rutas asociadas a las librerias de Hibernate --> <!-- 1 ruta: /hibernate-2.1/hibernate2.jar --> <fileset dir="${hibernate}"> <include name="hibernate2.jar"/> </fileset> <!-- 2 ruta: /hibernate-2.1/lib/*.jar --> <fileset dir="${hibernate}/lib"> <include name="*.jar"/> </fileset> <!-- 3 ruta: /hibernate-2.1/tools/*.jar --> <fileset dir="${hibernate.extensions}/lib"> <include name="*.jar"/> </fileset> <fileset dir="${hibernate.extensions}"> <include name="hibernate-tools.jar"/> </fileset> <!-- ****************************************************** --> <fileset dir="."> <include name="mysql-connector-java-3.0.17-ga-bin.jar"/> </fileset> </path>
Hibernate
14-13
<!-Se crean dos directorios, primero para el codigo de la clase que va a ser creada automaticamente y el segundo para los ficheros .class --> <target name="init"> <mkdir dir="${dirFuente}"/> <mkdir dir="${dirEjecutable}"/> </target> <!-- ************************************************************* Se define una tarea que genera automaticamente una clase Java a partir de informacin de configuracin: Catalog.hbm.xml --> <!-- ************************************************************* --> <taskdef name="javaGen" classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask" classpathref="project.class.path" /> <target name="javaGenerator" depends="init"> <javaGen output="${dirFuente}"> <fileset dir="${hibernate.mappings}"> <include name="Catalog.hbm.xml"/> </fileset> </javaGen> </target> <!-- ************************************************************* --> <!-- ************************************************************* Se define una tarea para compilar las clases que han sido generadas
14-14
Hibernate
automticamente --> <target name="compile" depends="javaGenerator"> <javac srcdir="${dirFuente}" destdir="${dirEjecutable}"> <classpath refid="project.class.path"/></javac> </target> <!-- ************************************************************* --> <taskdef name="schemaGen" classname="net.sf.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="project.class.path"/> <target name="schemaGenerator" depends="compile"> <schemaGen properties="${hibernate.properties}/hibernate.properties" quiet="no"> <fileset dir="${hibernate.mappings}"> <include name="Catalog.hbm.xml"/> </fileset> </schemaGen> </target> </project>
Base de Datos
Con respecto a la base de datos, slo decir que el driver JDBC para ella debe incluirse en nuestro proyecto.
Hibernate
14-15
Configuracin
Introduccin
Debido a que Hibernate ha sido diseado para que pueda trabajar en distintos entornos, existen una gran cantidad de parmetros de configuracin. Hibernate es un sistema altamente configurable para adaptarse a esto. Para configurar Hibernate se deben realizar: Configuracin del servicio Hibernate. Proporcionar a Hibernate toda la informacin asociada a las clases que se quieren hacer persistentes. La configuracin de estas clases permitir eliminar ese salto entre objetos y bases de datos relacionales.
Configuracin bsica
Hibernate proporciona dos posibles ficheros de configuracin: Fichero de propiedades estndar de Java (hibernate.properties). Fichero XML normalmente llamado hibernate.cfg.xml. Ambos ficheros llevan a cabo la misma tarea (configuracin del servicio Hibernate). Si ambos ficheros se encuentran en el classpath de la aplicacin, el segundo sobreescribe al primero. Se muestra a continuacin un ejemplo del fichero hibernate.cfg.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-
14-16
Hibernate
3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.username">uid</property> <property name="connection.password">pwd</property> <property name="connection.url"> jdbc:mysql://localhost/db </property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <mapping resource="com/manning/hq/ch03/Event.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Location.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Speaker.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Attendee.hbm.xml"/> </session-factory> </hibernate-configuration>
Aunque es bastante habitual encontrar una configuracin algo distinta combinando ambos ficheros:
<?xml version="1.0"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="show_sql">true</property> <mapping resource="com/manning/hq/ch03/Event.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Attendee.hbm.xml"/>
Hibernate
14-17
Estos ficheros se utilizan para configurar el tipo de conexin que se va a generar contra la base de datos y las clases que se van a asociar a las tablas.
Ficheros de mapeo
Son usados para proporcionar toda la informacin necesaria para asociar objetos a la tablas de la base de datos con la que queremos trabajar. Las definiciones de mapeo pueden guardarse juntas en un nico fichero de mapeo. Existe tambin la posibilidad de generar un fichero para cada uno de los objetos. Esta segunda opcin es la ms recomendable. La extensin para este tipo de ficheros es .hbm.xml. Por ejemplo, si tenemos una clase llamada Usuario, su fichero de mapeo asociado ser Usuario.hbm.xml.
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "//Hibernate/Hibernate Mapping DTD 2.0//EN"
14-18
Hibernate
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="entidades.Usuario" table="Usuario"> <id name="id" type="int" column="UsuarioId"> <generator class="native"/> </id> <property name="nombre" type="string"/> <property name="primerApellido" column="apellido1" type="string"/> <property name="segundoApellido" column="apellido2" type="string"/> <property name="direccion" type="string"/> <property name="telefono" type="int"/> </class> </hibernate-mapping>
Inmediatamente despus de la etiqueta <hibernate-mapping> se encuentra la etiqueta <class ... > que indica el inicio de la definicin de mapeo para una especfica clase. El atributo table define el nombre de la tabla de la base de datos relacional usada para almacenar el estado de los objetos. La etiqueta id describe la clave primaria para la clase persistente. Cada clase persistente debe tener un id declarando una clave primaria en la tabla. El atributo name define la propiedad de la clase que almacenar el valor de la clave primaria. Cada etiqueta property corresponde con una propiedad en el objeto.
Hibernate
14-19
Como se muestra, se debe configurar la conexin incorporando en el fichero los datos habituales (nombre de usuario, contrasea, url, ...). La informacin de mapeo se incorporara en el fichero xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="show_sql">true</property> <mapping resource="com/manning/hq/ch03/Event.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Attendee.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Speaker.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Location.hbm.xml"/> </session-factory> </hibernate-configuration>
14-20
Hibernate
Otra posible opcin es incluir toda la informacin de configuracin en el fichero xml hibernate.cfg.xml:
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.username">uid</property> <property name="connection.password">pwd</property> <property name="connection.url"> jdbc:mysql://localhost/db </property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <mapping resource="com/manning/hq/ch03/Event.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Location.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Speaker.hbm.xml"/> <mapping resource="com/manning/hq/ch03/Attendee.hbm.xml"/> </session-factory> </hibernate-configuration>
Aadir tablas es una tarea muy habitual cuando se trabaja con bases de datos (CREATE TABLE).
Hibernate
14-21
Para realizar esta tarea Hibernate incluye una tarea Ant (SchemaExport) que, apoyndose en ficheros de mapeo, clases y el fichero de configuracin hibernate.cfg.xml, genera tablas en una base de datos. El fichero build.xml estara configurado de la siguiente manera:
... <target name="schema-export" depends="compile" > <taskdef name="schemaexport" classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"> <classpath refid="runtime.classpath" /> </taskdef> <schemaexport config="${src.java.dir}/hibernate.cfg.xml"/> </target> ...
Esta tarea necesita conocer: Clases compiladas. Biblioteca Hibernate. Driver MySql. Fichero hibernate.cfg.xml.
14-22
Hibernate
Hibernate
14-23
void setWeight(float weight) { this.weight = weight; } public float getWeight() { return weight; } public Color getColor() { return color; } void setColor(Color color) { this.color = color; } void setSex(char sex) { this.sex=sex; } public char getSex() { return sex; } void setLitterId(int id) { this.litterId = id; } public int getLitterId() { return litterId; } void setMother(Cat mother) { this.mother = mother; } public Cat getMother() { return mother; } void setKittens(Set kittens) { this.kittens = kittens; } public Set getKittens() {
14-24
Hibernate
return kittens; } // addKitten not needed by Hibernate public void addKitten(Cat kitten) { kitten.setMother(this); kitten.setLitterId( kittens.size() ); kittens.add(kitten); } }
Estas clases deben cumplir cuatro condiciones: Implementar un constructor sin argumentos. Proporcionar una propiedad identificadora (opcional). Clase no final (opcional). Mtodos getter y setter para cada campo (opcional). Estas clases deben estar asociadas a un fichero de mapeo. Veamos un ejemplo sencillo. Supongamos que tenemos la clase Usuario con el siguiente cdigo:
package hibernatejsf; public class Usuario { private private private private private private Integer id; String nombre; String primerApellido; String segundoApellido; String direccion; Integer telefono;
public Usuario() {
Hibernate
14-25
} public void setId(Integer id) { this.id = id; } public Integer getId() { return id; } public void setNombre(String nombre) { this.nombre = nombre; } public String getNombre() { return nombre; } public void setPrimerApellido(String primerApellido) { this.primerApellido = primerApellido; } public String getPrimerApellido() { return primerApellido; } public void setSegundoApellido(String segundoApellido) { this.segundoApellido = segundoApellido; } public String getSegundoApellido() { return segundoApellido; } public void setDireccion(String direccion) { this.direccion = direccion; } public String getDireccion() { return direccion; } public void setTelefono(Integer telefono) { this.telefono = telefono; }
14-26
Hibernate
Hibernate proporciona la posibilidad de crear clases persistentes diseando nica y exclusivamente ficheros de mapero (mapping files). Esto es lo que se conoce como Modelo Dinmico. Para realizar esta tarea Hibernate incluye una tarea Ant:
...
Hibernate
14-27
<taskdef name="javaGen" classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask" classpathref="project.class.path" /> <target name="javaGenerator" depends="init"> <javaGen output="${dirFuente}"> <fileset dir="${hibernate.mappings}"> <include name="Catalog.hbm.xml"/> </fileset> </javaGen> </target> ...
14-28
Hibernate
Hibernate
14-29
Persists an unordered, non-unique collection of values or objects. array N/A Persists an indexed, non-unique collection of values or objects. Persists an indexed, non-unique collection of primitive values. Persists an unordered, non-unique, many-to-many collection using a surrogate key.
14-30
Hibernate
} public Set getSpeakers() { return this.speakers; } public void setAttendees(Set attendees) { this.attendees = attendees; } public Set getAttendees () { return this.attendees; } ... }
Hibernate
14-31
14-32
Hibernate
Para configurar SessionFactory tendremos que apoyarnos en la clase Configuration. Es usada para cargar los ficheros de mapeo y crear la Sessionfactory. Existen tres formas distintas de crear e inicializar el objeto Configuration.
Configuration configuracion = new Configuration(); SessionFactory f= configuracion.configure().buildSessionFactory() ;
El mtodo configure() hace que Hibernate cargue el fichero hibernate.cfg.xml. Sin esto el nico fichero que sera cargado sera hibernate.properties. Adems, la clase Configuration puede cargar ficheros de mapeo de forma programtica:
Configuration configuracion = new Configuration(); configuracion.addFile(com/manning/hq/ch03/Event.hbm.xml); SessionFactory f= configuracion.configure().buildSessionFactory() ;
Cuando el nmero de ficheros de mapeo crece demasiado es recomendable agruparlos todos en un fichero con extensin .jar.
Hibernate
14-33
...
14-34
Hibernate
// Crear un objeto Usuario u= new Usuario(); u.setNombre(Antonio); u.setPrimerApellido(Cruz); ... Configuration configuracion = new Configuration(); configuracion.addClass(com.manning.hq.ch03.Usuario.class); SessionFactory f= configuracion.configure().buildSessionFactory() ; Session sesion= f.openSession(); sesion.save(u); sesion.flush(); ...
Devolviendo objetos
El mtodo load nos permite recuperar objetos siempre y cuando conozcamos el identificador de dicho objeto:
Event event = (Event) session.load(Event.class, eventId); session.close();
El problema surge cuando no se conoce el identificador del objeto. Ese es el momento en el que se debe utilizar HQL. Veamos varios ejemplos:
Query query = session.createQuery("from Event");
Hibernate
14-35
14-36
Hibernate
Esta consulta devuelve todas las instancias a Event que se encuentran en la base de datos. Existen dos formas dentro de las APIs de Hibernate que nos permiten ejecutar consultas:
Mtodos find
Por ejemplo:
List results = session.find("from Event");
Hibernate
14-37
La interface Session tiene un mtodo iterador que nos permite recorrer la lista de forma cmoda:
Iterator results = session.iterate("from Event"); while (results.hasNext()) { Event myEvent = (Event) results.next(); // ... }
14-38
Hibernate
Interface Query
Esta interface es creada por la sesin y proporciona mayor control sobre los objetos devueltos:
Hibernate
14-39
Query tambin proporciona un iterador para realizar recorridos sobre las colecciones de datos, mtodo iterate(). En determinadas ocasiones podemos hacer que se comporte como un PreparedStatement de JDBC:
Query q = session.createQuery("from Event where name = ? "); q.setParameter(0, "Opening Plenary"); List results = q.list();
Existe otro mecanismo muy interesante llamado (:nombreParametro). Se muestra un ejemplo ilustrativo:
named
parameters
Query q = session.createQuery("from Event where name = :name"); q.setParameter("name", "Opening Plenary"); List results = q.list();
14-40
Hibernate
Este parmetro puede aparecer en la consulta tantas veces como sea necesario:
Query q = session.createQuery("from Event where "+ "startDate = :startDate or endDate < :startDate"); q.setParameter("startDate", eventStartDate); List results = q.list();
Clasulas HQL
Clasula FROM Esta clasula te permite especificar los objetos que ests buscando. Permite crear alias. Ejemplo:
from Event e where e.name='Opening Plenary'
Nota: No est permitido el uso de as. Clasula JOIN Se quieren devolve todos los eventos que han sido atendidos por el elemento identificado por el siguiente id:
from Event e join e.attendees a where a.id=314
Hibernate
14-41
Clasula SELECT Esta clasula permite especificar una lista de valores a ser devueltos por la consulta. Esta clasula no est forzada a devolver objetos completos, puede devolver campos aislados:
select e.name from Event e
Cada elemento en la lista devuelta es un array de Object con dos elementos. Veamos un ejemplo algo mayor:
Session session = factory.openSession(); String query = " select e.name, e.startDate from Event e "; Query query = session.createQuery("query"); List results = query.list(); for (Iterator I = results.iterator(); i.hasNext();) { Object[] row = (Object[]) i.next(); String name = (String) row[0]; Date startDate = (Date) row[1]; // ...
14-42
Hibernate
Hibernate Caching
Cacheado de sesin
Una forma sencilla de mejorar las prestaciones de una aplicacin dentro del servicio Hibernate, es el cacheo de objetos. El almacenamiento de objetos en memoria evita a Hibernate tener que acceder a la base de datos cada vez que necesita devolver un objeto. Se muestra un ejemplo ilustrativo:
Session session = factory.openSession(); Event e = (Event) session.load(Event.class, myEventId); e.setName("New Event Name"); session.saveOrUpdate(e); // later, with the same Session instance Event e = (Event) session.load(Event.class, myEventId); e.setDuration(180); session.saveOrUpdate(e); session.flush();
Se devuelve una instancia de un objeto, ste es cacheado por la sesin internamente. Todas las actualizaciones realizados sobre ese objeto son combinadas en una nica actualizacin cuando se flushea la sesin. La interface Session tiene acceso a una cach para cada objeto que es cargado y guardado durante el tiempo de vida de esa sesin.
Hibernate
14-43
Transacciones Hibernate
Introduccin
Una transaccin es un conjunto de operaciones agrupada en una nica unidad de trabajo. Si alguna operacin de ese conjunto falla todas las operaciones se deshacen. Hibernate puede ejecutarse en muy diferentes entornos soportando distintos tipos de transacciones. Aplicaciones independientes y algn servidor slo soportan transacciones JDBC, en cambio, hay otras que soportan JTA (Java Transaction API). Hibernate necesita una forma de abstraer las distintas estrategas en funcin del entorno en el que se encuentra. Se define la clase y la interface Transaction para afrontar ese problema:
Session session = factory.openSession(); Transaction tx = session.beginTransaction(); Event event = new Event(); // ... populate the Event instance session.saveOrUpdate(event); tx.commit();
14-44
Hibernate
Interface Transaction
Clase Transaction
Esta clase implementa la interface Transaction y ofrece un conjunto de mtodos:
Hibernate
14-45
Configuracin de Transacciones
La propiedad transaction.factory_class define cul es la estrategia de transacciones que utiliza Hibernate. Por defecto se utilizan transacciones JDBC. Para usar JTA se debe configurar el fichero hibernate.cfg.xml de la siguiente manera:
14-46
Hibernate
... <property name="transaction.factory_class"> org.hibernate.transaction.JTATransactionFactory </property> <property name="jta.UserTransaction"> java:comp/UserTransaction </property> ...
Hibernate
14-47
14-48
Hibernate
public class SimpleEventDao { Log log = LogFactory.getLog(SimpleEventDao.class); private Session session; private Transaction tx; public SimpleEventDao() { HibernateFactory.buildIfNeeded(); } /** * Insert a new Event into the database. * @param event */ public void create(Event event) throws DataAccessLayerException { try { startOperation(); session.save(event); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { HibernateFactory.close(session); } }
Hibernate
14-49
/** * Delete a detached Event from the database. * @param event */ public void delete(Event event) throws DataAccessLayerException { try { startOperation(); session.delete(event); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { HibernateFactory.close(session); } } /** * Find an Event by its primary key. * @param id * @return */
14-50
Hibernate
public Event find(Long id) throws DataAccessLayerException { Event event = null; try { startOperation(); event = (Event) session.load(Event.class, id); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { HibernateFactory.close(session); } return event; } /** * Updates the state of a detached Event. * * @param event */ public void update(Event event) throws DataAccessLayerException {
Hibernate
14-51
try { startOperation(); session.update(event); tx.commit(); } catch (HibernateException e) { handleException(e); } finally { HibernateFactory.close(session); } } /** * Finds all Events in the database. * @return */ public List findAll() throws DataAccessLayerException{ List events = null; try { startOperation(); Query query = session.createQuery("from Event");
14-52
Hibernate
events =
query.list();
tx.commit(); } catch (HibernateException e) { handleException(e); } finally { HibernateFactory.close(session); } return events; } private void handleException(HibernateException e) throws DataAccessLayerException { HibernateFactory.rollback(tx); throw new DataAccessLayerException(e); } private void startOperation() throws HibernateException { session = HibernateFactory.openSession(); tx = session.beginTransaction();
Hibernate
14-53
} }