HIBERNATE - Persist en CIA Re..1

Embed Size (px)

Citation preview

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

(21) (20) (19) (18) (17) (16)

HIBERNATE - Persistencia relacional para Java idiomticoDocumentacin de referencia de Hibernatepor Gavin King, Christian Bauer, Max Rydahl Andersen, Emmanuel Bernard, y Steve Ebersole and thanks to James Cobb (Graphic Design), Cheyenne Weaver (Graphic Design), y Bernardo Antonio Buffa Colom

3.5.6-FinalCopyright 2004 Red Hat, Inc. Advertencia legal September 15, 2010

Prefacio 1. Tutorial 1.1. Parte 1 - La primera aplicacin Hibernate 1.1.1. Configuracin 1.1.2. La primera clase 1.1.3. El archivo de mapeo 1.1.4. Configuracin de Hibernate 1.1.5. Construccin con Maven 1.1.6. Inicio y ayudantes 1.1.7. Carga y almacenamiento de objetos 1.2. Part 2 - Mapeo de asociaciones 1.2.1. Mapeo de la clase Person 1.2.2. Una asociacin unidireccional basada en Set 1.2.3. Trabajo de la asociacin 1.2.4. Coleccin de valores 1.2.5. Asociaciones bidireccionales 1.2.6. Trabajo con enlaces bidireccionales 1.3. Part 3 - La aplicacin web EventManager 1.3.1. Escritura de un servlet bsico 1.3.2. Procesamiento y entrega 1.3.3. Despliegue y prueba 1.4. Resumen 2. Arquitectura 2.1. Sinopsis 2.2. Estados de instancia 2.3. Integracin JMX 2.4. Soporte JCA 2.5. Sesiones contextuales 3. Configuracin 3.1. Configuracin programtica 3.2. Obtencin de una SessionFactory 3.3. Conexiones JDBC 3.4. Parmetros de configuracin opcionales 3.4.1. Dialectos de SQL 3.4.2. Recuperacin por Unin Externa - Outer Join Fetching 3.4.3. Flujos Binarios 3.4.4. Cach de segundo nivel y de lectura 3.4.5. Sustitucin de Lenguaje de Consulta 3.4.6. Estadsticas de Hibernate 3.5. Registros de mensajes (Logging) 3.6. Implementacin de una NamingStrategy 3.7. Archivo de configuracin XML 3.8. Integracin con Servidores de Aplicaciones J2EE 3.8.1. Configuracin de la estrategia de transaccin

1 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

3.8.2. SessionFactory enlazado a JNDI 3.8.3. Administracin de contexto de Sesin Actual con JTA 3.8.4. Despliegue JMX 4. Clases persistentes 4.1. Ejemplo simple de POJO 4.1.1. Implemente un constructor sin argumentos 4.1.2. Proporcione una propiedad identificadora (opcional) 4.1.3. Prefiera las clases no finales (opcional) 4.1.4. Declare mtodos de acceso y de modificacin para los campos persistentes (opcional) 4.2. Implementacin de herencia 4.3. Implementando equals() y hashCode() 4.4. Modelos dinmicos 4.5. Tuplizers 4.6. EntityNameResolvers 5. Mapeo O/R Bsico 5.1. Declaracin de mapeo 5.1.1. Doctype 5.1.2. Mapeo de Hibernate 5.1.3. Clase 5.1.4. id 5.1.5. Generadores mejorados del identificador 5.1.6. Optimizacin del generador del identificador 5.1.7. composite-id 5.1.8. Discriminador 5.1.9. Versin (opcional) 5.1.10. Timestamp (opcional) 5.1.11. Propiedad 5.1.12. Many-to-one 5.1.13. One-to-one 5.1.14. Natural-id 5.1.15. Componente y componente dinmico 5.1.16. Propiedades 5.1.17. Subclase 5.1.18. joined-subclass 5.1.19. Union-subclass 5.1.20. Join 5.1.21. Key 5.1.22. Los elementos columna y frmula 5.1.23. Import 5.1.24. Any 5.2. Tipos de Hibernate 5.2.1. Entidades y Valores 5.2.2. Tipos de valores bsicos 5.2.3. Tipos de valor personalizados 5.3. Mapeo de una clase ms de una vez 5.4. Identificadores SQL en comillas 5.5. Alternativas de metadatos 5.5.1. Utilizacin de marcado de XDoclet 5.5.2. Utlizacin de Anotaciones JDK 5.0 5.6. Propiedades generadas 5.7. Expresiones de lectura y escritura de columnas 5.8. Objetos de bases de datos auxiliares 6. Mapeos de coleccin 6.1. Colecciones persistentes 6.2. Mapeos de coleccin 6.2.1. Claves forneas de coleccin 6.2.2. Elementos de colleccin 6.2.3. Colecciones indexadas 6.2.4. Colecciones de valores y asociaciones muchos-a-muchos 6.2.5. Asociaciones uno-a-muchos 6.3. Mapeos de coleccin avanzados 6.3.1. Colecciones ordenadas 6.3.2. Asociaciones bidireccionales 6.3.3. Asociaciones bidireccionales con colecciones indexadas 6.3.4. Asociaciones ternarias 6.3.5. Using an 6.4. Ejemplos de coleccin 7. Mapeos de asociacin 7.1. Introduccin 7.2. Asociaciones Unidireccionales 7.2.1. Many-to-one 7.2.2. Uno-a-uno 7.2.3. Uno-a-muchos 7.3. Asociaciones unidireccionales con tablas de unin

2 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

7.3.1. Uno-a-muchos 7.3.2. Many-to-one 7.3.3. Uno-a-uno 7.3.4. Muchos-a-muchos 7.4. Asociaciones bidireccionales 7.4.1. uno-a-muchos / muchos-a-uno 7.4.2. Uno-a-uno 7.5. Asociaciones bidireccionales con tablas de unin 7.5.1. uno-a-muchos / muchos-a-uno 7.5.2. uno a uno 7.5.3. Muchos-a-muchos 7.6. Mapeos de asociacin ms complejos 8. Mapeo de componentes 8.1. Objetos dependientes 8.2. Colecciones de objetos dependientes 8.3. Componentes como ndices de Mapeo 8.4. Componentes como identificadores compuestos 8.5. Componentes dinmicos 9. Mapeo de herencias 9.1. Las tres estrategias 9.1.1. Tabla por jerarqua de clases 9.1.2. Tabla por subclase 9.1.3. Tabla por subclase: utilizando un discriminador 9.1.4. Mezcla de tabla por jerarqua de clases con tabla por subclase 9.1.5. Tabla por clase concreta 9.1.6. Tabla por clase concreta utilizando polimorfismo implcito 9.1.7. Mezcla de polimorfismo implcito con otros mapeos de herencia 9.2. Limitaciones 10. Trabajo con objetos 10.1. Estados de objeto de Hibernate 10.2. Haciendo los objetos persistentes 10.3. Cargando un objeto 10.4. Consultas 10.4.1. Ejecucin de consultas 10.4.2. Filtracin de colecciones 10.4.3. Consultas de criterios 10.4.4. Consultas en SQL nativo 10.5. Modificacin de objetos persistentes 10.6. Modificacin de objetos separados 10.7. Deteccin automtica de estado 10.8. Borrado de objetos persistentes 10.9. Replicacin de objetos entre dos almacenamientos de datos diferentes 10.10. Limpieza (flushing) de la sesin 10.11. Persistencia transitiva 10.12. Utilizacin de metadatos 11. Read-only entities 11.1. Making persistent entities read-only 11.1.1. Entities of immutable classes 11.1.2. Loading persistent entities as read-only 11.1.3. Loading read-only entities from an HQL query/criteria 11.1.4. Making a persistent entity read-only 11.2. Read-only affect on property type 11.2.1. Simple properties 11.2.2. Unidirectional associations 11.2.3. Bidirectional associations 12. Transacciones y concurrencia 12.1. mbitos de sesin y de transaccin 12.1.1. Unidad de trabajo 12.1.2. Conversaciones largas 12.1.3. Consideracin de la identidad del objeto 12.1.4. Temas comnes 12.2. Demarcacin de la transaccin de la base de datos 12.2.1. Entorno no administrado 12.2.2. Utilizacin de JTA 12.2.3. Manejo de excepciones 12.2.4. Tiempo de espera de la transaccin 12.3. Control de concurrencia optimista 12.3.1. Chequeo de versiones de la aplicacin 12.3.2. Sesin extendida y versionado automtico 12.3.3. Objetos separados y versionado automtico 12.3.4. Personalizacin del versionado automtico 12.4. Bloqueo pesimista 12.5. Modos de liberacin de la conexin

3 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

13. Interceptores y eventos 13.1. Interceptores 13.2. Sistema de eventos 13.3. Seguridad declarativa de Hibernate 14. Procesamiento por lotes 14.1. Inserciones de lotes 14.2. Actualizaciones de lotes 14.3. La interfaz de Sesin sin Estado 14.4. Operaciones de estilo DML 15. HQL: El lenguaje de consulta de Hibernate 15.1. Sensibilidad a maysculas 15.2. La clusula from 15.3. Asociaciones y uniones (joins) 15.4. Formas de sintaxis unida 15.5. Referencia a la propiedad identificadora 15.6. La clusula select 15.7. Funciones de agregacin 15.8. Consultas polimrficas 15.9. La clusula where 15.10. Expresiones 15.11. La clusula order by 15.12. La clusula group by 15.13. Subconsultas 15.14. Ejemplos de HQL 15.15. Declaraciones UPDATE y DELETE masivas 15.16. Consejos y Trucos 15.17. Componentes 15.18. Sintaxis del constructor de valores por fila 16. Consultas por criterios 16.1. Creacin de una instancia Criteria 16.2. Lmitando el conjunto de resultados 16.3. Orden de los resultados 16.4. Asociaciones 16.5. Recuperacin dinmica de asociaciones 16.6. Consultas ejemplo 16.7. Proyecciones, agregacin y agrupamiento 16.8. Consultas y subconsultas separadas 16.9. Consultas por identificador natural 17. SQL Nativo 17.1. Uso de una SQLQuery 17.1.1. Consultas escalares 17.1.2. Consultas de entidades 17.1.3. Manejo de asociaciones y colecciones 17.1.4. Devolucin de entidades mltiples 17.1.5. Devolucin de entidades no-administradas 17.1.6. Manejo de herencias 17.1.7. Parmetros 17.2. Consultas SQL nombradas 17.2.1. Utilizacin de la propiedad return para especificar explcitamente los nombres de columnas/alias 17.2.2. Utilizacin de procedimientos para consultas 17.3. Personalice SQL para crear, actualizar y borrar 17.4. Personalice SQL para cargar 18. Filtracin de datos 18.1. Filtros de Hibernate 19. Mapeo XML 19.1. Trabajo con datos XML 19.1.1. Especificacin de los mapeos de XML y de clase en conjunto 19.1.2. Especificacin de slo un mapeo XML 19.2. Mapeo de metadatos XML 19.3. Manipulacin de datos XML 20. Mejoramiento del rendimiento 20.1. Estrategias de recuperacin 20.1.1. Trabajo con asociaciones perezosas 20.1.2. Afinacin de las estrategias de recuperacin 20.1.3. Proxies de asociaciones de un slo extremo 20.1.4. Inicializacin de colecciones y proxies 20.1.5. Utilizacin de recuperacin de lotes 20.1.6. Utilizacin de la recuperacin por subseleccin 20.1.7. Perfiles de recuperacin 20.1.8. Utilizacin de la recuperacin perezosa de propiedades 20.2. El Cach de Segundo Nivel 20.2.1. Mapeos de cach

4 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

20.2.2. Estrategia: slo lectura 20.2.3. Estrategia: lectura/escritura (read/write) 20.2.4. Estrategia: lectura/escritura no estricta 20.2.5. Estrategia: transaccional 20.2.6. Compatibilidad de proveedor de cach/estrategia de concurrencia 20.3. Gestin de cachs 20.4. El Cach de Consultas 20.4.1. Habilitacin del cach de peticiones 20.4.2. Regiones de cach de consultas 20.5. Comprensin del rendimiento de Colecciones 20.5.1. Taxonoma 20.5.2. Las listas, mapas, idbags y conjuntos son las colecciones ms eficientes de actualizar 20.5.3. Los Bags y las listas son las colecciones inversas ms eficientes 20.5.4. Borrado de un slo tiro 20.6. Control del rendimiento 20.6.1. Control de una SessionFactory 20.6.2. Mtricas 21. Manual del conjunto de herramientas 21.1. Generacin automtica de esquemas 21.1.1. Personalizacin del esquema 21.1.2. Ejecucin de la herramienta 21.1.3. Propiedades 21.1.4. Utilizacin de Ant 21.1.5. Actualizaciones incrementales de esquema 21.1.6. Utilizacin de Ant para actualizaciones incrementales de esquema 21.1.7. Validacin de Esquema 21.1.8. Utilizacin de Ant para la validacin de esquema 22. Ejemplo: Padre/Hijo 22.1. Nota sobre las colecciones 22.2. Uno-a-muchos bidireccional 22.3. Ciclo de vida en cascada 22.4. Cascadas y unsaved-value 22.5. Conclusin 23. Ejemplo: Aplicacin de Weblog 23.1. Clases Persistentes 23.2. Mapeos de Hibernate 23.3. Cdigo Hibernate 24. Ejemplo: mapeos varios 24.1. Empleador/Empleado 24.2. Autor/Obra 24.3. Cliente/Orden/Producto 24.4. Mapeos varios de ejemplo 24.4.1. Asociacin uno-a-uno "Tipificada" 24.4.2. Ejemplo de clave compuesta 24.4.3. Muchos-a-muchos con atributo compartido de clave compuesta 24.4.4. Discriminacin basada en contenido 24.4.5. Asociaciones sobre claves alternativas 25. Prcticas recomendadas 26. Consideraciones de la portabilidad de la base de datos 26.1. Aspectos bsicos de la portabilidad 26.2. Dialecto 26.3. Resolucin del dialecto 26.4. Generacin del identificador 26.5. Funciones de la base de datos 26.6. Mapeos de tipo Referencias

PrefacioEl trabajar con software orientado a objetos y con una base de datos relacional puede llegar a ser engorroso y puede llegar a tomar bastante tiempo en los entornos empresariales de hoy en da. Hibernate es una herramienta de mapeo objeto/relacional para entornos Java. El trmino de mapeo objeto/relacional (ORM) se refiere a la tcnica de mapear una representacin de datos desde un modelo de objeto a un modelo de datos relacionales con un esquema basado en SQL. Hibernate no slamente se ocupa del mapeo desde las clases Java a las tablas de las bases de datos (y desde los tipos de datos de Java a los tipos de datos de SQL), sino que tambin facilita la consulta y recuperacin de datos. Esto puede reducir de manera importante el tiempo de desarrollo que se tomara con el manejo de datos de forma manual en SQL y JDBC. La meta de Hibernate es aliviar el trabajo del desarrollador en 95% de la persistencia de datos comunes relacionados con tareas de programacin. Es posible que Hibernate no sea la mejor solucin para aquellas aplicaciones centralizadas en datos que slamente utilizan los procedimientos almacenados para

5 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

implementar la lgica empresarial en la base de datos, Hibernate es mucho ms til con modelos de dominio orientados a objetos y con lgica empresarial middle-tier con base en Java. Sin embargo, Hibernate ciertamente le puede ayudar a eliminar o a encapsular cdigo SQL especfico del vendedor y le ayudar con la tarea comn de traduccin del grupo de resultados desde una representacin tabular a un grafo de objetos. Si usted es nuevo en el tema de Hibernate y del Mapeo Objeto/Relacional o inclusive en Java por favor siga los siguientes pasos: 1. Read Captulo 1, Tutorial for a tutorial with step-by-step instructions. The source code for the tutorial is included in the distribution in the doc/reference/tutorial/ directory. 2. Read Captulo 2, Arquitectura to understand the environments where Hibernate can be used. 3. Dle un vistazo al directorio eg/ en la distribucin de Hibernate. Este comprende una aplicacin autnoma simple. Copie su compilador JDBC al directorio lib/ y edite etc/hibernate.properties , especificando los valores correctos para su base de datos. Desde un intrprete de comandos en el directorio de la distribucin, escriba ant eg (utilizando Ant), o bajo Windows, escriba build eg. 4. Use this reference documentation as your primary source of information. Consider reading [JPwH] if you need more help with application design, or if you prefer a step-by-step tutorial. Also visit http://caveatemptor.hibernate.org and download the example application from [JPwH]. 5. En el sitio web de Hibernate encontrar las respuestas a las preguntas ms frecuentes. 6. En el sitio web de Hibernate encontrar los enlaces a las demostraciones de terceros, ejemplos y tutoriales. 7. El rea de la comunidad en el sitio web de Hibernate es un buen recurso para encontrar patrones de diseo y varias soluciones de integracin (Tomcat, JBoss AS, Struts, EJB, etc). Si tiene alguna pregunta, dirjase al sitio web de Hibernate en donde encontrar un enlace al foro de usuarios. Tambin proporcionamos un sistema de localizacin para reportes de errores JIRA y solicitud de funciones. Si est interesado en el desarrollo de Hibernate, nase a la lista de correo de los desarrolladores. Si le interesa traducir esta documentacin a su propio idioma, contctenos en la lista de correo de los desarrolladores. JBoss Inc. proporciona soporte para desarrollo comercial, soporte para produccin y entrenamiento (vea http://www.hibernate.org/SupportTraining/). Hibernate es un proyecto de Cdigo Abierto Profesional y es un componente crtico de la suite de productos de JBoss Enterprise Middleware System (JEMS).

Captulo 1. Tutorial1.1. Parte 1 - La primera aplicacin Hibernate 1.1.1. Configuracin 1.1.2. La primera clase 1.1.3. El archivo de mapeo 1.1.4. Configuracin de Hibernate 1.1.5. Construccin con Maven 1.1.6. Inicio y ayudantes 1.1.7. Carga y almacenamiento de objetos 1.2. Part 2 - Mapeo de asociaciones 1.2.1. Mapeo de la clase Person 1.2.2. Una asociacin unidireccional basada en Set 1.2.3. Trabajo de la asociacin 1.2.4. Coleccin de valores 1.2.5. Asociaciones bidireccionales 1.2.6. Trabajo con enlaces bidireccionales 1.3. Part 3 - La aplicacin web EventManager 1.3.1. Escritura de un servlet bsico 1.3.2. Procesamiento y entrega 1.3.3. Despliegue y prueba 1.4. Resumen Dirigido a los nuevos usuarios, este captulo brinda una introduccin a Hibernate paso por paso, empezando con una aplicacin simple usando una base de datos en memoria. Este tutorial se basa en un tutorial anterior que Michael Gloegl desarroll. Todo el cdigo se encuentra en el directorio tutorials/web de la fuente del proyecto.

ImportanteEste tutorial se basa en que el usuario tenga conocimiento de Java y SQL. Si tiene un conocimiento muy limitado de JAVA o SQL, le aconsejamos que empiece con una buena introduccin a esta tecnologa antes de tratar de aprender sobre Hibernate.

6 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

NotaLa distribucin contiene otra aplicacin de ejemplo bajo el directorio fuente del proyecto tutorial/eg.

1.1. Parte 1 - La primera aplicacin HibernatePara este ejemplo, vamos a configurar una aplicacin base de datos pequea que pueda almacenar eventos a los que queremos asistir e informacin sobre los anfitriones de estos eventos.

NotaAunque puede utilizar cualquier base de datos con la que se sienta bien, vamos a usar HSQLDB (una base de datos Java en-memoria) para evitar describir la instalacin/configuracin de cualquier servidor de base de datos en particular.

1.1.1. ConfiguracinLo primero que tenemos que hacer es configurar el entorno de desarrollo. Vamos a utilizar el "diseo estndar" apoyado por muchas herramientas de construccin tal como Maven. Maven, en particular, tiene un buen recurso que describe este diseo. Como este tutorial va a ser una aplicacin web, vamos a crear y a utilizar los directorios src/main/java, src/main/resources y src/main/webapp. Vamos a usar Maven en este tutorial, sacando ventaja de sus funcionalidades de administracin de dependencias transitivas as como la habilidad de muchos IDEs para configurar automticamente un proyecto para nosotros con base en el descriptor maven.

7 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

javax.servlet servlet-api org.slf4j slf4j-simple javassist javassist

SugerenciaIt is not a requirement to use Maven. If you wish to use something else to build this tutorial (such as Ant), the layout will remain the same. The only change is that you will need to manually account for all the needed dependencies. If you use something like Ivy providing transitive dependency management you would still use the dependencies mentioned below. Otherwise, you'd need to grab all dependencies, both explicit and transitive, and add them to the project's classpath. If working from the Hibernate distribution bundle, this would mean hibernate3.jar, all artifacts in the lib/required directory and all files from either thelib/bytecode/cglib or lib/bytecode/javassist directory; additionally you will need both the

servlet-api jar and one of the slf4j logging backends.

Guarde este archivo como pom.xml en el directorio raz del proyecto.

1.1.2. La primera claseLuego creamos una clase que representa el evento que queremos almacenar en la base de datos, es una clase JavaBean simple con algunas propiedades:

8 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

package org.hibernate.tutorial.domain; import java.util.Date; public class Event { private Long id; private String title; private Date date; public Event() {} public Long getId() { return id; } private void setId(Long id) { this.id = id; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }

Esta clase utiliza convenciones de nombrado estndares de JavaBean para los mtodos de propiedades getter y setter as como tambin visibilidad privada para los campos. Se recomienda este diseo, pero no se exige. Hibernate tambin puede acceder a los campos directamente, los mtodos de acceso benefician la robustez de la refactorizacin. La propiedad id tiene un valor identificador nico para un evento en particular. Todas las clases de entidad persistentes necesitarn tal propiedad identificadora si queremos utilizar el grupo completo de funcionalidades de Hibernate (tambin algunas clases dependientes menos importantes). De hecho, la mayora de las aplicaciones (en especial las aplicaciones web) necesitan distinguir los objetos por identificador, as que usted debe tomar esto como una funcionalidad ms que una limitacin. Sin embargo, usualmente no manipulamos la identidad de un objeto, por lo tanto, el mtodo setter debe ser privado. Slamente Hibernate asignar identificadores cuando se guarde un objeto. Como se puede ver, Hibernate puede acceder a mtodos de acceso pblicos, privados y protegidos, as como tambin a campos directamente pblicos, privados y protegidos. Puede escoger y hacer que se ajuste a su diseo de su aplicacin. El constructor sin argumentos es un requerimiento para todas las clases persistentes, Hibernate tiene que crear objetos por usted utilizando Java Reflection. El constructor puede ser privado; sin embargo, se necesita la visibilidad del paquete para generar proxies en tiempo de ejecucin y para la recuperacin de datos de manera efectiva sin la instrumentacin del cdigo byte. Duarde este archivo en el directorio src/main/java/org/hibernate/tutorial/domain.

1.1.3. El archivo de mapeoHibernate necesita saber cmo cargar y almacenar objetos de la clase persistente. En este punto es donde entra en juego el archivo de mapeo de Hibernate. Este archivo le dice a Hibernate a que tabla tiene que acceder en la base de datos, y que columnas debe utilizar en esta tabla. La estructura bsica de un archivo de mapeo se ve as:

[...]

El DTD de Hibernate es sofisticado. Puede utilizarlo para autocompletar los elementos y atributos XML de mapeo en su editor o IDE. Abrir el archivo DTD en su editor de texto es la manera ms fcil para obtener una sinopsis de todos los elementos y atributos y para ver los valores por defecto, as como algunos de los comentarios. Note que Hibernate no cargar el fichero DTD de la web, sino que primero lo buscar en la ruta

9 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

de clase de la aplicacin. El archivo DTD se encuentra incluido en hibernate-core.jar (tambin enhibernate3.jar si est usando el paquete de la distribucin).

ImportanteOmitiremos la declaracin de DTD en los ejemplos posteriores para hacer ms corto el cdigo. Esto no es opcional.

Entre las dos etiquetas hibernate-mapping, incluya un elemento class . Todas las clases de entidad persistentes (de nuevo, podran haber clases dependientes ms adelante, las cuales no son entidades de primera clase) necesitan de dicho mapeo en una tabla en la base de datos SQL:

Hasta ahora le hemos dicho a Hibernate cmo persistir y cargar el objeto de clase Event a la tabla EVENTS. Cada instancia se encuentra representada por una fila en esa tabla. Ahora podemos continuar mapeando la propiedad identificadora nica a la clave primaria de la tabla. Ya que no queremos preocuparnos por el manejo de este identificador, configuramos la estrategia de generacin del identificador de Hibernate para una columna clave primaria sustituta:

El elemento id es la declaracin de la propiedad identificadora. El atributo de mapeo name="id" declara el nombre de la propiedad JavaBean y le dice a Hibernate que utilice los mtodos getId() y setId() para acceder a la propiedad. El atributo columna le dice a Hibernate qu columna de la tabla EVENTS tiene el valor de la llave principal. El elemento anidado generator especifica la estrategia de generacin del identificador (tambin conocidos como cmo se generan los valores del identificador?). En este caso escogimos native , el cual ofrece un nivel de qu tan porttil es dependiendo del dialecto configurado de la base de datos. Hibernate soporta identificadores generados por la base de datos, globalmente nicos as como asignados por la aplicacin. La generacin del valor del identificador tambin es uno de los muchos puntos de extensin de Hibernate y puede conectar su propia estrategia.

Sugerencianative is no longer consider the best strategy in terms of portability. for further discussion, see

Seccin 26.4, Generacin del identificador

Por ltimo es necesario decirle a Hibernate sobre las porpiedades de clase de entidad que quedan. Por defecto, ninguna propiedad de la clase se considera persistente:

Al igual que con el elemento id, el atributo name del elemento property le dice a Hibernate que mtodos getter y setter utilizar. As que en este caso, Hibernate buscar los mtodos getDate(), setDate(), getTitle() ysetTitle().

10 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

NotaPor qu el mapeo de la propiedad date incluye el atributo column, pero el de title no? Sin el atributo column Hibernate utiliza, por defecto, el nombre de propiedad como nombre de la columna. Esto funciona bien para title. Sin embargo, date es una palabra clave reservada en la mayora de las bases de datos, as que es mejor que la mapeamos a un nombre diferente.

El mapeo de title carece de un atributo type . Los tipos que declaramos y utilizamos en los archivos de mapeo no son tipos de datos Java. Tampoco son tipos de base de datos SQL. Estos tipos se llaman tipos de mapeo Hibernate , convertidores que pueden traducir de tipos de datos de Java a SQL y viceversa. De nuevo, Hibernate tratar de determinar el tipo correcto de conversin y de mapeo por s mismo si el atributo type no se encuentra presente en el mapeo. En algunos casos esta deteccin automtica (utilizando Reflection en la clase Java) puede que no tenga lo que usted espera o necesita. Este es el caso de la propiedad date . Hibernate no puede saber is la propiedad, la cual es de java.util.Date , debe mapear a una columna date ,timestamp o time de SQL. Por medio de un convertidor timestamp, mapeamos la propiedad y mantenemos la

informacin completa sobre la hora y fecha.

SugerenciaHibernate realiza esta determinacin de tipo de mapeo usando reflection cuando se procesan los archivos de mapeo. Esto puede tomar tiempo y recursos as que el rendimiento al arrancar es importante entonces debe considerar el definir explcitamente el tipo a usar.

Guarde este archivo de mapeo como src/main/resources/org/hibernate/tutorial/domain/Event.hbm.xml.

1.1.4. Configuracin de HibernateEn este momento debe tener la clase persistente y su archivo de mapeo. Ahora debe configurar Hibernate. Primero vamos a configurar HSQLDB para que ejecute en "modo de servidor"

NotaHacemos esto o lo otro y los datos permanecen entre ejecuciones.

Vamos

a

utilizar

el

plugin

de

ejecucin

Maven

para

lanzar

el

servidor

HSQLDB

ejecutando:

mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0 file:target/data/tutorial".Lo

ver iniciando y vinculandose a un enchufe TCP/IP, all es donde nuestra aplicacin se conectar ms adelante. Si quiere dar inicio con una base de datos fresca durante este tutorial, apague HSQLDB, borre todos los archivos en el directorio target/data e inicie HSQLDB de nuevo. Hibernate se conectar a la base de datos de parte de su aplicacin as que necesita saber cmo obtener conexiones. Para este tutorial vamos a utilizar un pool de conexiones autnomo (opuesto a javax.sql.DataSource ). Hibernate viene con soporte para dos pools de conexiones JDBC de cdigo abierto de terceros: c3p0 y proxool. Sin embargo, vamos a utilizar el pool de conexiones incluido de Hibernate para este tutorial.

AtencinEl pool de conexiones de Hibernate no est diseado para utilizarse en produccin. Le faltan varias funcionalidades que se encuentran en cualquier pool de conexiones decente.

Para la configuracin de Hibernate, podemos utilizar un archivo hibernate.properties simple, un archivohibernate.cfg.xml un poco ms sofisticado, o incluso una configuracin completamente programtica. La

mayora de los usuarios prefieren el archivo de configuracin XML:

11 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

org.hsqldb.jdbcDriver jdbc:hsqldb:hsql://localhost sa 1 org.hibernate.dialect.HSQLDialect thread org.hibernate.cache.NoCacheProvider true update

NotaObserve que este archivo de configuracin especifica un DTD diferente

Configure la SessionFactory de Hibernate. SessionFactory es una fbrica global responsable de una base de datos en particular. Si usted tiene varias bases de datos, para un inicio ms fcil utilice varias configuraciones en varios archivos de configuracin. Los primeros cuatro elementos property contienen la configuracin necesaria para la conexin JDBC. El elemento property dialecto especifica la variante SQL en particular que Hibernate genera.

SugerenciaIn most cases, Hibernate is able to properly determine which dialect to use. See Seccin 26.3, Resolucin del dialecto for more information.

La administracin de la sesin automtica de Hibernate para contextos de persistencia es particularmente til en este contexto. La opcin hbm2ddl.auto activa la generacin automtica de los esquemas de la base de datos directamente en la base de datos. Esto se puede desactivar, eliminando la opcin de configuracin o redirigindolo a un archivo con la ayuda de la tarea de Ant SchemaExport . Finalmente, agregue a la configuracin el/los fichero(s) de mapeo para clases persistentes. Guarde este archivo como hibernate.cfg.xml en el directorio src/main/resources.

1.1.5. Construccin con MavenAhora vamos a construir el tutorial con Maven. Es necesario que tenga instalado Maven; se encuentra disponible en la pgina de descargas Maven. Maven leer el archivo /pom.xml que creamos anteriormente y sabr cmo realizar algunas tareas de proyectos bsicos. Primero, vamos a ejecutar la meta compile para

12 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

asegurarnos de que podemos compilar todo hasta el momento:[hibernateTutorial]$ mvn compile [INFO] Scanning for projects... [INFO] -----------------------------------------------------------------------[INFO] Building First Hibernate Tutorial [INFO] task-segment: [compile] [INFO] -----------------------------------------------------------------------[INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 1 source file to /home/steve/projects/sandbox/hibernateTutorial/target/classes [INFO] -----------------------------------------------------------------------[INFO] BUILD SUCCESSFUL [INFO] -----------------------------------------------------------------------[INFO] Total time: 2 seconds [INFO] Finished at: Tue Jun 09 12:25:25 CDT 2009 [INFO] Final Memory: 5M/547M [INFO] ------------------------------------------------------------------------

1.1.6. Inicio y ayudantesEs el momento de cargar y almacenar algunos objetos Event , pero primero tiene que completar la configuracin con algo de cdigo de infraestructura. Tiene que iniciar Hibernate construyendo un objeto org.hibernate.SessionFactory global y almacenarlo en algn lugar de fcil acceso en el cdigo de la aplicacin. Unaorg.hibernate.SessionFactory

se

utiliza

para

obtener

instancias

org.hibernate.Session.

Una

org.hibernate.Session representa una unidad de trabajo mono-hilo. La org.hibernate.SessionFactory es un objeto

global seguro entre hilos que se instancia una sla vez. Vamos a crear una clase de ayuda HibernateUtil que se encargue del inicio y haga ms prctico el acceso aorg.hibernate.SessionFactory. package org.hibernate.tutorial.util; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml return new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }

Guarde este cdigo como src/main/java/org/hibernate/tutorial/util/HibernateUtil.java Esta clase no slamente produce la referencia org.hibernate.SessionFactory global en su inicializador esttico, sino que tambin esconde el hecho de que utiliza un singleton esttico. Tambin puede que busque la referencia org.hibernate.SessionFactory desde JNDI en un servidor de aplicaciones en cualquier otro lugar. Si usted le da un nombre a org.hibernate.SessionFactory en su archivo de configuracin, de hecho, Hibernate tratar de vincularlo a JNDI bajo ese nombre despus de que ha sido construido. Otra mejor opcin es utilizar el despliegue JMX y dejar que el contenedor con capacidad JMX instancie y vincule un HibernateService a JNDI. Ms adelante discutiremos estas opciones avanzadas. Ahora necesita configurar un sistema de registro. Hibernate utiliza registros comunes le da dos opciones: Log4J y registros de JDK 1.4. La mayora de los desarrolladores prefieren Log4J: copie log4j.properties de la distribucin de Hibernate, se encuentra en el directorio etc/) a su directorio src, junto a hibernate.cfg.xml . Si desea tener una salida ms verbosa que la que se proporcion en la configuracin del ejemplo entonces puede cambiar su configuracin. Por defecto, slo se muestra el mensaje de inicio de Hibernate en la salida estndar. La infraestructura del tutorial est completa y estamos listos para hacer un poco de trabajo real con Hibernate.

13 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

1.1.7. Carga y almacenamiento de objetosWe are now ready to start doing some real work with Hibernate. Let's start by writing an EventManager class with a main() method:package org.hibernate.tutorial; import org.hibernate.Session; import java.util.*; import org.hibernate.tutorial.domain.Event; import org.hibernate.tutorial.util.HibernateUtil; public class EventManager { public static void main(String[] args) { EventManager mgr = new EventManager(); if (args[0].equals("store")) { mgr.createAndStoreEvent("My Event", new Date()); } HibernateUtil.getSessionFactory().close(); } private void createAndStoreEvent(String title, Date theDate) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle(title); theEvent.setDate(theDate); session.save(theEvent); session.getTransaction().commit(); } }

En createAndStoreEvent() creamos un nuevo objeto Event y se lo entregamos a Hibernate. En ese momento, Hibernate se encarga de SQL y ejecuta un INSERT en la base de datos. A org.hibernate.Session is designed to represent a single unit of work (a single atomic piece of work to be performed). For now we will keep things simple and assume a one-to-one granularity between a Hibernate org.hibernate.Session and a database transaction. To shield our code from the actual underlying transaction system we use the Hibernate org.hibernate.Transaction API. In this particular case we are using JDBC-based transactional semantics, but it could also run with JTA. Qu hace sessionFactory.getCurrentSession()? Primero, la puede llamar tantas veces como desee y en donde quiera, una vez consiga su org.hibernate.SessionFactory. El mtodo getCurrentSession() siempre retorna la unidad de trabajo "actual". Recuerda que cambiamos la opcin de la configuracin de este mecanismo a "thread" en src/main/resources/hibernate.cfg.xml? Por lo tanto, el contexto de una unidad de trabajo actual se encuentra vinculada al hilo de Java actual que ejecuta nuestra aplicacin.

ImportanteHibernate ofrece tres mtodos de rastreo de sesin actual. El mtodo basado en "hilos" no est dirigido al uso de produccin; slo es til para prototipos y para tutoriales como este. Ms adelante discutiremos con ms detalles el rastreo de sesin actual.

Una org.hibernate.Session se inicia cuando se realiza la primera llamada a getCurrentSession() para el hilo actual. Luego Hibernate la vincula al hilo actual. Cuando termina la transaccin, ya sea por medio de guardar o deshacer los cambios, Hibernate desvincula automticamente la org.hibernate.Session del hilo y la cierra por usted. Si llama a getCurrentSession() de nuevo, obtiene una org.hibernate.Session nueva y obtiene una nueva org.hibernate.Session unidad de trabajo. En relacin con la unidad del campo de trabajo, Se debera utilizar org.hibernate.Session de Hibernate para ejecutar una o varias operaciones de la base de datos? El ejemplo anterior utiliza una org.hibernate.Session para una operacin. Sin embargo, esto es pura coincidencia; el ejemplo simplemente no es lo suficientemente complicado para mostrar cualquier otro enfoque. El mbito de una org.hibernate.Session de Hibernate es flexible pero nunca debe disear su aplicacin para que utilice una nueva org.hibernate.Session de Hibernate para cada operacin de la base de datos. Aunque lo utilizamos en los siguientes ejemplos, considere la sesin-por-operacin como un anti-patrn. Ms adelante en este tutorial, se muestra una aplicacin web real, lo cual le ayudar a ilustrar esto. See Captulo 12, Transacciones y concurrencia for more information about transaction handling and demarcation. The previous example also skipped any error handling and rollback.

14 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

Para ejecutar esto, utilizaremos el plugin de ejecucin Maven para llamar nuestra clase con la configuracin de ruta de clase necesaria:mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store"

NotaEs posible que primero necesite realizar mvn compile .

Debe ver que Hibernate inicia y dependiendo de su configuracin, tambin ver bastantes salidas de registro. Al final, ver la siguiente lnea:[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)

Este es el INSERT que Hibernate ejecuta. Para listar los eventos almacenados se agrega una opcin al mtodo principal:if (args[0].equals("store")) { mgr.createAndStoreEvent("My Event", new Date()); } else if (args[0].equals("list")) { List events = mgr.listEvents(); for (int i = 0; i < events.size(); i++) { Event theEvent = (Event) events.get(i); System.out.println( "Event: " + theEvent.getTitle() + " Time: " + theEvent.getDate() ); } }

Tambin agregamos un mtodo listEvents():private List listEvents() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); List result = session.createQuery("from Event").list(); session.getTransaction().commit(); return result; }

Here, we are using a Hibernate Query Language (HQL) query to load all existing Event objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populate Event objects with the data. You can create more complex queries with HQL. See Captulo 15, HQL: El lenguaje de consulta de Hibernate for more information. Ahora podemos llamar nuestra nueva funcionalidad, de nuevo usando el plugin de ejecucin Maven:mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list"

1.2. Part 2 - Mapeo de asociacionesHasta ahora hemos mapeado una clase de entidad persistente a una tabla aislada. Vamos a construir sobre esto y agregaremos algunas asociaciones de clase. Vamos a agregar personas a la aplicacin y vamos a almacenar una lista de eventos en las que participan.

1.2.1. Mapeo de la clase PersonEl primer corte de la clase Person se ve as:package org.hibernate.tutorial.domain; public class Person { private private private private Long id; int age; String firstname; String lastname;

public Person() {} // Accessor methods for all properties, private setter for 'id' }

Guarde esto en un archivo llamado src/main/java/org/hibernate/tutorial/domain/Person.java Luego, cree el nuevo archivo de mapeo como

15 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

src/main/resources/org/hibernate/tutorial/domain/Person.hbm.xml

Finalmente, aada el nuevo mapeo a la configuracin de Hibernate:

Vamos a crear una asociacin entre estas dos entidades. Las personas pueden participar en los eventos y los eventos cuentan con participantes. Las cuestiones de diseo con las que tenemos que tratar son: direccionalidad, multiplicidad y comportamiento de la coleccin.

1.2.2. Una asociacin unidireccional basada en SetAl agregar una coleccin de eventos a la clase Person, puede navegar fcilmente a los eventos de una persona en particular, sin ejecutar una peticin explcita - llamando a Person#getEvents . En Hibernate, las asociaciones multi-valores se representan por medio de uno de los contratos del marco de colecciones Java; aqu escogimos un java.util.Set ya que la coleccin no contendr elementos duplicados y el orden no es relevante para nuestros ejemplos.public class Person { private Set events = new HashSet(); public Set getEvents() { return events; } public void setEvents(Set events) { this.events = events; } }

Antes de mapear esta asociacin, considere el otro lado. Podriamos mantener esto unidireccional o podramos crear otra coleccin en el Event , si queremos tener la habilidad de navegarlo desde ambas direcciones. Esto no es necesario desde un punto de vista funcional. Siempre puede ejeutar un pedido explcito para recuperar los participantes de un evento en particular. Esta es una eleccin de diseo que depende de usted, pero lo que queda claro de esta discusin es la multiplicidad de la asociacin: "muchos" valuada en ambos lados, denominamos esto como una asociacin muchos-a-muchos. Por lo tanto, utilizamos un mapeo muchos-a-muchos de Hibernate:

Hibernate soporta un amplio rango de mapeos de coleccin, el ms comn set . Para una asociacin muchosa-muchos o la relacin de entidad n:m, se necesita una tabla de asociacin. Cada fila en esta tabla representa un enlace entre una persona y un evento. El nombre de esta tabla se declara con el atributo table del elemento set . El nombre de la columna identificadora en la asociacin, del lado de la persona, se define con el elemento key, el nombre de columna para el lado del evento se define con el atributo column delmany-to-many. Tambin tiene que informarle a Hibernate la clase de los objetos en su coleccin (la clase del

otro lado de la coleccin de referencias). Por consiguiente, el esquema de base de datos para este mapeo es:

16 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

_____________ __________________ | | | | _____________ | EVENTS | | PERSON_EVENT | | | |_____________| |__________________| | PERSON | | | | | |_____________| | *EVENT_ID | | *EVENT_ID | | | | EVENT_DATE | | *PERSON_ID | | *PERSON_ID | | TITLE | |__________________| | AGE | |_____________| | FIRSTNAME | | LASTNAME | |_____________|

1.2.3. Trabajo de la asociacinVamos a reunir a algunas personas y eventos en un nuevo mtodo en EventManager:private void addPersonToEvent(Long personId, Long eventId) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson = (Person) session.load(Person.class, personId); Event anEvent = (Event) session.load(Event.class, eventId); aPerson.getEvents().add(anEvent); session.getTransaction().commit(); }

Despus de cargar una Person y un Event , simplemente modifique la coleccin utilizando los mtodos normales de coleccin. No hay una llamada explcita a update() o save(); Hibernate detecta automticamente que se ha modificado la coleccin y que se necesita actualizarla. Esto se denomina chequeo automtico de desactualizaciones y tambin puede probarlo modificando el nombre o la propiedad de fecha de cualquiera de sus objetos. Mientras se encuentran en estado persistente, es decir, enlazado a una org.hibernate.Session de Hibernate en particular, Hibernate monitorea cualquier cambio y ejecuta SQL de un modo escribe-detrs. El proceso de sincronizacin del estado de la memoria con la base de datos, usualmente slo al final de una unidad de trabajo, se denomina vaciado. En nuestro cdigo la unidad de trabajo termina con guardar o deshacer los cambios de la transaccin de la base de datos. Puede cargar una persona y un evento en diferentes unidades de trabajo. Tambin puede modificar un objeto fuera de una org.hibernate.Session, cuando no se encuentra en estado persistente (si antes era persistente denominamos a este estado separado ). Inclusive, puede modificar una coleccin cuando se encuentre separada:private void addPersonToEvent(Long personId, Long eventId) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson = (Person) session .createQuery("select p from Person p left join fetch p.events where p.id = :pid" .setParameter("pid", personId) .uniqueResult(); // Eager fetch the collection so we can use it detached Event anEvent = (Event) session.load(Event.class, eventId); session.getTransaction().commit(); // End of first unit of work aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached // Begin second unit of work Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); session2.update(aPerson); // Reattachment of aPerson session2.getTransaction().commit(); }

La llamada a update hace que un objeto separado sea persistente de nuevo enlazndolo a una nueva unidad de trabajo, as que cualquier modificacin que le realiz mientras estaba separado se puede guardar en la base de datos. Esto incluye cualquier modificacin (adiciones o eliminaciones) que le hizo a una coleccin de ese objeto entidad. Esto no se utiliza mucho en nuestro ejemplo, pero es un concepto importante que puede incorporar en su propia aplicacin. Complete este ejercicio agregando una nueva accin al mtodo main de EventManager y llmela desde la lnea de comandos. Si necesita los identificadores de una persona y de un evento - el mtodo save() los retorna (pueda que necesite modificar algunos de los mtodos anteriores para retornar ese identificador):

17 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

else if (args[0].equals("addpersontoevent")) { Long eventId = mgr.createAndStoreEvent("My Event", new Date()); Long personId = mgr.createAndStorePerson("Foo", "Bar"); mgr.addPersonToEvent(personId, eventId); System.out.println("Added person " + personId + " to event " + eventId); }

Esto fue un ejemplo de una asociacin entre dos clases igualmente importantes: dos entidades. Como se mencion anteriormente, hay otras clases y tipos en un modelo tpico, usualmente "menos importantes". Algunos de ustedes las habrn visto, como un int o un java.lang.String. Denominamos a estas clases tipos de valor y sus instancias dependen de una entidad en particular. Las instancias de estos tipos no tienen su propia identidad, ni son compartidas entre entidades. Dos personas no referencian el mismo objeto firstname , incluso si tienen el mismo nombre. Los tipos de valor no slo pueden encontrarse en el JDK, sino que tambin puede escribir por s mismo clases dependientes como por ejemplo, Address o MonetaryAmount . De hecho, en una aplicacin Hibernate todas las clases JDK se consideran como tipos de valor. Tambin puede disear una coleccin de tipos de valor. Esto es conceptualmente diferente de una coleccin de referencias a otras entidades, pero se ve casi igual en Java.

1.2.4. Coleccin de valoresVamos a agregar una coleccin de direcciones de correo electrnico a la entidad Person. Esto se representar como un java.util.Set de las instnaicas java.lang.String:private Set emailAddresses = new HashSet(); public Set getEmailAddresses() { return emailAddresses; } public void setEmailAddresses(Set emailAddresses) { this.emailAddresses = emailAddresses; }

El mapeo de este Set es as:

La diferencia comparado con el mapeo anterior es el uso de la parte element , que le dice a Hibernate que la coleccin no contiene referencias a otra entidad, sino que es una coleccin de elementos que son tipos de valores, aqu especificamente de tipo String. El nombre en minsculas le dice que es un tipo/conversor de mapeo de Hibernate. Una vez ms, el atributo table del elemento set determina el nombre de la tabla para la coleccin. El elemento key define el nombre de la columna clave fornea en la tabla de coleccin. El atributo column en el elemento element define el nombre de la columna donde realmente se almacenarn los valores de la direccin de correo electrnico. Este es el esquema actualizado:_____________ __________________ | | | | _____________ | EVENTS | | PERSON_EVENT | | | ___________________ |_____________| |__________________| | PERSON | | | | | | | |_____________| | PERSON_EMAIL_ADDR | | *EVENT_ID | | *EVENT_ID | | | |___________________| | EVENT_DATE | | *PERSON_ID | | *PERSON_ID | | *PERSON_ID | | TITLE | |__________________| | AGE | | *EMAIL_ADDR | |_____________| | FIRSTNAME | |___________________| | LASTNAME | |_____________|

Puede ver que la clave principal de la tabla de coleccin es, de hecho, una clave compuesta que utiliza ambas columnas. Esto tambin implica que no pueden haber direcciones de correo electrnico duplicadas por persona, la cual es exactamente la semntica que necesitamos para un conjunto en Java. Ahora, puede tratar de agregar elementos a esta coleccin, al igual que lo hicimos antes vinculando personas y eventos. Es el mismo cdigo en Java.

18 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

private void addEmailToPerson(Long personId, String emailAddress) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson = (Person) session.load(Person.class, personId); // adding to the emailAddress collection might trigger a lazy load of the collection aPerson.getEmailAddresses().add(emailAddress); session.getTransaction().commit(); }

Esta vez no utilizamos una peticin de bqueda - fetch - para dar inicio a la coleccin. Monitoree su registro SQL e intente de optimizar esto con una recuperacin temprana.

1.2.5. Asociaciones bidireccionalesA continuacion vamos a mapear una asociacin bidireccional. Vamos a hacer que la asociacin entre persona y evento funcione desde ambos lados en Java. El esquema de la base de datos no cambia as que todava tendremos una multiplicidad muchos-a-muchos.

NotaUna base de datos relacional es ms flexible que un lenguaje de programacin de red ya que no necesita una direccin de navegacin; los datos se pueden ver y recuperar de cualquier forma posible.

Primero, agregue una coleccin de participantes a la clase Event :private Set participants = new HashSet(); public Set getParticipants() { return participants; } public void setParticipants(Set participants) { this.participants = participants; }

Ahora mapee este lado de la asociacin en Event.hbm.xml .

Estos son mapeos normales de set en ambos documentos de mapeo. Note que los nombres de las columnas en key y many-to-many se intercambiaron en ambos documentos de mapeo. La adicin ms importante aqu es el atributo inverse="true" en el elemento set del mapeo de coleccin de Event . Esto significa que Hibernate debe tomar el otro lado, la clase Person, cuando necesite encontrar informacin sobre el enlace entre las dos. Esto ser mucho ms fcil de entender una vez que vea como se crea el enlace bidireccional entre nuestras dos entidades.

1.2.6. Trabajo con enlaces bidireccionalesPrimero, recuerde que Hibernate no afecta la semntica normal de Java. Cmo creamos un enlace entre Person y un Event en el ejemplo unidireccional? Agregue una instancia de Event a la coleccin de referencias de eventos de una instancia de Person. Si quiere que este enlace funcione bidireccionalmente, tiene que hacer lo mismo del otro lado, aadiendo una referencia Person a la coleccin en un Event . Este proceso de "establecer el enlace en ambos lados" es absolutamente necesario con enlaces bidireccionales. Muchos desarrolladores programan a la defensiva y crean mtodos de administracin de enlaces para establecer correctamente ambos lados, (por ejemplo, en Person):

19 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

protected Set getEvents() { return events; } protected void setEvents(Set events) { this.events = events; } public void addToEvent(Event event) { this.getEvents().add(event); event.getParticipants().add(this); } public void removeFromEvent(Event event) { this.getEvents().remove(event); event.getParticipants().remove(this); }

Los mtodos get y set para la coleccin ahora se encuentran protegidos. Esto le permite a las clases en el mismo paquete y a las subclases acceder an a los mtodos, pero impide a cualquier otro que desordene las colecciones directamente. Repita los pasos para la coleccin del otro lado. Y el atributo de mapeo inverse? Para usted y para Java, un enlace bidireccional es simplemente cuestin de establecer correctamente las referencias en ambos lados. Sin embargo, Hibernate no tiene suficiente informacin para organizar correctamente declaraciones INSERT y UPDATE de SQL (para evitar violaciones de restricciones). El hacer un lado de la asociacin inverse le dice a Hibernate que lo considere un espejo del otro lado. Eso es todo lo necesario para que Hibernate resuelva todos los asuntos que surgen al transformar un modelo de navegacin direccional a un esquema de base de datos SQL. Las reglas son muy simples: todas las asociaciones bidireccionales necesitan que uno de los lados sea inverse. En una asociacin uno-a-muchos debe ser el lado-de-muchos; y en una asociacin muchos-a-muchos, puede escoger cualquier lado.

1.3. Part 3 - La aplicacin web EventManagerUna aplicacin web de Hibernate utiliza Session y Transaction casi como una aplicacin autnoma. Sin embargo, algunos patrones comunes son tiles. Ahora puede escribir un EventManagerServlet . Este servlet puede enumerar todos los eventos almacenados en la base de datos y proporciona una forma HTML para ingresar eventos nuevos.

1.3.1. Escritura de un servlet bsicoPrimero necesitamos crear nuestro servlet de procesamiento bsico. Ya que nuestro servlet solo maneja pedidos GET HTTP slamente, solo implementaremos el mtodo doGet():package org.hibernate.tutorial.web; // Imports public class EventManagerServlet extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { SimpleDateFormat dateFormatter = new SimpleDateFormat( "dd.MM.yyyy" ); try { // Begin unit of work HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction(); // Process request and render page... // End unit of work HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit(); } catch (Exception ex) { HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback(); if ( ServletException.class.isInstance( ex ) ) { throw ( ServletException ) ex; } else { throw new ServletException( ex ); } } } }

Guarde este servlet como src/main/java/org/hibernate/tutorial/web/EventManagerServlet.java El patrn aplicado aqu se llama sesin-por-peticin. Cuando una peticin llega al servlet, se abre una nueva

20 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

Session de Hibernate por medio de la primera llamada a getCurrentSession() en el SessionFactory. Entonces se

inicia una transaccin de la base de datos. Todo acceso a los datos tiene que suceder dentro de una transaccin, sin importar que los datos sean ledos o escritos . No utilice el modo auto-commit en las aplicaciones. No utilice una nueva Session de Hibernate para cada operacin de base de datos. Utilice una Session Hibernate que cubra el campo de todo el pedido. Utilice getCurrentSession() para vincularlo automticamente al hilo de Java actual. Despus, se procesan las acciones posibles del pedido y se entrega la respuesta HTML. Llegaremos a esa parte muy pronto. Finalmente, la unidad de trabajo termina cuando se completa el procesamiento y la entrega. Si surgi algn problema durante el procesamiento o la entrega , se presentar una excepcin y la transaccin de la base de datos se deshar. Esto completa el patrn session-per-request . En vez del cdigo de demarcacin de la transaccin en todo servlet, tambin podra escribir un filtro de servlet. Va el sitio web de Hibernate y el Wiki para obtener ms informacin sobre este patrn llamado sesin abierta en vista. Lo necesitar tan pronto como considere representar su vista en JSP, no en un servlet.

1.3.2. Procesamiento y entregaAhora puede implementar el procesamiento del pedido y la representacin de la pgina.// Write HTML header PrintWriter out = response.getWriter(); out.println("Event Manager"); // Handle actions if ( "store".equals(request.getParameter("action")) ) { String eventTitle = request.getParameter("eventTitle"); String eventDate = request.getParameter("eventDate"); if ( "".equals(eventTitle) || "".equals(eventDate) ) { out.println("Please enter event title and date."); } else { createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); out.println("Added event."); } } // Print page printEventForm(out); listEvents(out, dateFormatter); // Write HTML footer out.println(""); out.flush(); out.close();

Dado que este estilo de codificacin con una mezcla de Java y HTML no escalara en una aplicacin ms compleja - tenga en cuenta que slo estamos ilustrando los conceptos bsicos de Hibernate en este tutorial. El cdigo imprime una cabecera y un pie de pgina HTML. Dentro de esta pgina se imprime una forma HTML para entrada de eventos y se imprime una lista de todos los eventos en la base de datos. El primer mtodo es trivial y su salida se realiza nicamente en HTML:private void printEventForm(PrintWriter out) { out.println("Add new event:"); out.println(""); out.println("Title:
"); out.println("Date (e.g. 24.12.2009):
"); out.println(""); out.println(""); }

21 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

El mtodo listEvents() utiliza Hibernate Session vinculado al hilo actual para ejecutar una peticin:private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) { List result = HibernateUtil.getSessionFactory() .getCurrentSession().createCriteria(Event.class).list(); if (result.size() > 0) { out.println("Events in database:"); out.println(""); out.println(""); out.println("Event title"); out.println("Event date"); out.println(""); Iterator it = result.iterator(); while (it.hasNext()) { Event event = (Event) it.next(); out.println(""); out.println("" + event.getTitle() + ""); out.println("" + dateFormatter.format(event.getDate()) + ""); out.println(""); } out.println(""); } }

Finalmente, la accin store se despacha al mtodo createAndStoreEvent(), el cual tambin utiliza la Session del hilo actual:protected void createAndStoreEvent(String title, Date theDate) { Event theEvent = new Event(); theEvent.setTitle(title); theEvent.setDate(theDate); HibernateUtil.getSessionFactory() .getCurrentSession().save(theEvent); }

El servlet se encuentra completo. Un pedido al servlet ser procesado en una sola Session y Transaction. Como lo vimos antes en la aplicacin autnoma, Hibernate puede enlazar automticamente estos objetos al hilo actual de ejecucin. Esto le da la libertad de utilizar capas en su cdigo y acceder a la SessionFactory de cualquier manera que lo desee. Usualmente, usted utilizara un diseo ms sofisticado y movera el cdigo de acceso de datos a los objetos de acceso de datos (el patrn DAO). Refirase al Wiki de Hibernate para ver ms ejemplos.

1.3.3. Despliegue y pruebaPara implementar esta aplicacin para prueba debemos crear una Web ARchive (WAR). Primero debemos definir el descriptor WAR como src/main/webapp/WEB-INF/web.xml

22 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

java:/comp/env/jdbc/MyDB org.hibernate.dialect.MySQLDialect false org.hibernate.transaction.JTATransactionFactory java:comp/UserTransaction

La ventaja de este enfoque es la externalizacin de los nombres de los archivos de mapeo a la configuracin. El hibernate.cfg.xml tambin es ms prctico una vez que haya afinado el cach de Hibernate. Puede escoger ya sea hibernate.properties o hibernate.cfg.xml . Ambos son equivalentes, excepto por los beneficios de utilizar la sintaxis XML que mencionados anteriormente. Con la configuracin XML, iniciar Hibernate es tan simple como:SessionFactory sf = new Configuration().configure().buildSessionFactory();

Puede seleccionar un fichero de configuracin XML diferente utilizando:SessionFactory sf = new Configuration() .configure("catdb.cfg.xml") .buildSessionFactory();

3.8. Integracin con Servidores de Aplicaciones J2EEHibernate tiene los siguientes puntos de integracin con la infraestructura J2EE: Fuentes de datos administrados por el contenedor: Hibernate puede utilizar conexiones JDBC administradas por el contenedor y provistas a travs de JNDI. Usualmente, un TransactionManager compatible con JTA y un ResourceManager se ocupan de la administracin de transacciones (CMT), especialmente del manejo de transacciones distribudas a travs de varias fuentes de datos. Tambin puede demarcar los lmites de las transacciones programticamente (BMT) o puede que quiera utilizar para esto la API opcional de Transaction de Hibernate para mantener porttil su cdigo. Vinculacin Automtica JNDI: Hibernate puede vincular sus SessionFactory a JNDI despus del inicio. Vinculacin de Sesin JTA: La Session de Hibernate se puede vincular automticamente al mbito de transacciones JTA. Simplemente busque la SessionFactory de JNDI y obtnga la Session actual. Deje que Hibernate se ocupe de vaciar y cerrar la Session cuando se complete su transaccin JTA. La demarcacin de transaccin puede ser declarativa (CMT) o programtica (BMT/UserTransaction). Despliegue JMX: Si tiene un servidor de aplicaciones con capacidad para JMX (por ejemplo, JBoss AS), puede escoger el desplegar Hibernate como un MBean administrado. Esto le ahorra el cdigo de una lnea de inicio para construir su SessionFactory desde una Configuration. El contenedor iniciar suHibernateService , e idealmente tambin cuidar de las dependencias entre servicios (la fuente de datos

debe estar disponible antes de que Hibernate inicie, etc). Dependiendo de su entorno, podra tener que establecer la opcin de configuracin como true si su servidor de aplicaciones muestra excepciones

hibernate.connection.aggressive_release

36 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

"contencin de conexin".

3.8.1. Configuracin de la estrategia de transaccinLa API de Session de Hibernate es independiente de cualquier demarcacin de transaccin en su arquitectura. Si deja que Hibernate utilice JDBC directamente, a travs de un pool de conexiones, puede comenzar y acabar sus transacciones llamando la API de JDBC. Si ejecuta en un servidor de aplicaciones J2EE, puede que quiera utilizar transacciones administradas por bean y llamar la API de JTA y UserTransaction cuando sea necesario. Para mantener su cdigo portable entre estos dos (y otros) entornos le recomendamos la API de Transaction de Hibernate, que envuelve y oculta el sistema subyacente. Tiene que especificar una clase fbrica para las instancias de Transaction estableciendo la propiedad de configuracin hibernate.transaction.factory_class de Hibernate. Existen tres opciones estndares o incorporadas:org.hibernate.transaction.JDBCTransactionFactory

delega a transacciones de bases de datos (JDBC) (por defecto)org.hibernate.transaction.JTATransactionFactory

delega a transacciones administradas por el contenedor si una transaccin existente se encuentra en proceso en este contexto (por ejemplo, un mtodo de bean de sesin EJB). De otra manera, se inicia una nueva transaccin y se utilizan las transacciones administradas por bean.org.hibernate.transaction.CMTTransactionFactory

delega a transacciones JTA administradas por el contenedor Tambin puede definir sus propias estrategias de transaccin (por ejemplo, para un servicio de transaccin CORBA). Algunas funcionalidades en Hibernate (por ejemplo, el cach de segundo nivel, las sesiones contextuales, etc.) requieren acceso al TransactionManager de JTA en un entorno administrado. En un servidor de aplicaciones tiene que especificar cmo Hibernate debe obtener una referencia al TransactionManager, ya que J2EE no estandariza un slo mecanismo:

Tabla 3.10. TransactionManagers de JTA Transaction Factoryorg.hibernate.transaction.JBossTransactionManagerLookup org.hibernate.transaction.WeblogicTransactionManagerLookup org.hibernate.transaction.WebSphereTransactionManagerLookup org.hibernate.transaction.WebSphereExtendedJTATransactionLookup org.hibernate.transaction.OrionTransactionManagerLookup org.hibernate.transaction.ResinTransactionManagerLookup org.hibernate.transaction.JOTMTransactionManagerLookup org.hibernate.transaction.JOnASTransactionManagerLookup org.hibernate.transaction.JRun4TransactionManagerLookup org.hibernate.transaction.BESTransactionManagerLookup

Servidor de Aplicaciones JBoss Weblogic WebSphere WebSphere 6 Orion Resin JOTM JOnAS JRun4 Borland ES

3.8.2. SessionFactory enlazado a JNDIUna SessionFactory de Hibernate vinculada a JNDI puede simplificar la bsqueda de la fbrica y la creacin de nuevas Sessiones. Sin embargo, esto no se relaciona con un Datasource vinculado a JNDI; simplemente que ambos utilizan el mismo registro. Si desea tener la SessionFactory vinculada a un espacio de nombres de JNDI, especifique un nombre (por ejemplo, java:hibernate/SessionFactory) utilizando la propiedad hibernate.session_factory_name. Si se omite esta propiedad, la SessionFactory no ser vinculada a JNDI. Esto es particularmente til en entornos con una implementacin JNDI de slo lectura por defecto (por ejemplo, en Tomcat). Al vincular la SessionFactory a JNDI, Hibernate utilizar los valores de hibernate.jndi.url , hibernate.jndi.class para instanciar un contexto inicial. Si stos no se especifican, se utilizar el InitialContext por defecto. Hibernate colocar automticamente laSessionFactory

en

JNDI

despus

de

que

llame

a

cfg.buildSessionFactory(). Esto significa que tendr al menos esta llamada en algn cdigo de inicio o clase de

utilidad en su aplicacin, a menos de que utilice el despliegue JMX con el HibernateService (esto se discute ms adelante en mayor detalle).

37 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

Si utiliza una SessionFactory JNDI, un EJB or cualquier otra clase puede llegar a obtener el SessionFactory utilizando una bsqueda JNDI. Le recomendamos que vincule el SessionFactory a JNDI en un entorno administrado y que de otra manera, use un singleton static. Para proteger su cdigo de aplicacin de estos detalles, tambin le recomendamos que esconda el cdigo de bsqueda real para una SessionFactory en una clase de ayuda comoHibernateUtil.getSessionFactory(). Note que dicha clase tambin es una manera prctica de iniciar Hibernate

vea el captulo 1.

3.8.3. Administracin de contexto de Sesin Actual con JTAThe easiest way to handle Sessions and transactions is Hibernate's automatic "current" Session management. For a discussion of contextual sessions see Seccin 2.5, Sesiones contextuales. Using the "jta" session context, if there is no Hibernate Session associated with the current JTA transaction, one will be started and associated with that JTA transaction the first time you call sessionFactory.getCurrentSession(). The Sessions retrieved via getCurrentSession() in the "jta" context are set to automatically flush before the transaction completes, close after the transaction completes, and aggressively release JDBC connections after each statement. This allows the Sessions to be managed by the life cycle of the JTA transaction to which it is associated, keeping user code clean of such management concerns. Your code can either use JTA programmatically through UserTransaction, or (recommended for portable code) use the Hibernate Transaction API to set transaction boundaries. If you run in an EJB container, declarative transaction demarcation with CMT is preferred.

3.8.4. Despliegue JMXLa lnea cfg.buildSessionFactory() todava se tiene que ejecutar en algn sitio para obtener una SessionFactory en JNDI. Puede hacer esto ya sea en un bloque inicializador static (como aquel en HibernateUtil ) o bien puede desplegar Hibernate como un servicio administrado. Hibernate se distribuye con org.hibernate.jmx.HibernateService para desplegar en un servidor de aplicaciones con capacidades JMX, como JBoss AS. El despliegue y la configuracn reales son especficos del vendedor. He aqu un ejemplo de jboss-service.xml para JBoss 4.0.x:

38 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

jboss.jca:service=RARDeployer jboss.jca:service=LocalTxCM,name=HsqlDS java:/hibernate/SessionFactory java:HsqlDS org.hibernate.dialect.HSQLDialect org.hibernate.transaction.JTATransactionFactory org.hibernate.transaction.JBossTransactionManagerLookup true true 5 true org.hibernate.cache.EhCacheProvider true true auction/Item.hbm.xml,auction/Category.hbm.xml

Este archivo se implementa en un directorio llamado META-INF y se encuentra empacado en un archivo JAR con la extensin .sar (archivo de servicio). Tambin necesita empacar Hibernate, sus bibliotecas de terceros requeridas, sus clases persistentes compiladas, as como sus archivos de mapeo en el mismo archivo. Sus beans empresariales (usualmente beans de sesin) se pueden dejar en su propio archivo JAR, pero puede incluir este archivo EJB JAR en el archivo de servicio principal para obtener una unidad desplegable en vivo (sin apagarlo). Consulte la documentacin de JBoss AS para obtener ms informacin sobre el servicio JMX y la implementacin de EJB.

Captulo 4. Clases persistentes4.1. Ejemplo simple de POJO 4.1.1. Implemente un constructor sin argumentos 4.1.2. Proporcione una propiedad identificadora (opcional) 4.1.3. Prefiera las clases no finales (opcional) 4.1.4. Declare mtodos de acceso y de modificacin para los campos persistentes (opcional) 4.2. Implementacin de herencia 4.3. Implementando equals() y hashCode() 4.4. Modelos dinmicos 4.5. Tuplizers 4.6. EntityNameResolvers Las clases presistentes son clases en una aplicacin que implementan las entidades del problema empresarial (por ejemplo, Customer y Order en una aplicacin de comercio electrnico). No se considera que todas las instancias de una clase persistente estn en estado persistente. Por ejemplo, una instancia puede ser transitoria o separada.

39 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

Hibernate funciona mejor si estas clases siguen algunas reglas simples, tambin conocidas como el modelo de programacin POJO (Plain Old Java Object). Sin embargo, ninguna de estas reglas son requerimientos rgidos. De hecho, Hibernate3 asume muy poco acerca de la naturaleza de sus objetos persistentes. Puede expresar un modelo de dominio en otras formas (por ejemplo, utilizando rboles de instancias de Map).

4.1. Ejemplo simple de POJOLa mayora de aplicaciones Java requieren una clase persistente que represente a los felinos. Por ejemplo:package eg; import java.util.Set; import java.util.Date; public class Cat { private Long id; // identifier private private private private private Date birthdate; Color color; char sex; float weight; int litterId;

private Cat mother; private Set kittens = new HashSet(); private void setId(Long id) { this.id=id; } public Long getId() { return id; } void setBirthdate(Date date) { birthdate = date; } public Date getBirthdate() { return birthdate; } 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() { return kittens; } // addKitten not needed by Hibernate public void addKitten(Cat kitten) { kitten.setMother(this); kitten.setLitterId( kittens.size() ); kittens.add(kitten); } }

40 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

En las siguientes secciones vamos a explorar en mayor detalle las cuatro reglas principales de las clases persistentes.

4.1.1. Implemente un constructor sin argumentosCat

tiene un contructor sin argumentos. Todas las clases persistentes deben tener un constructor

predeterminado (el cual puede ser no-pblico) de modo que Hibernate pueda instanciarlas usando Constructor.newInstance(). Le recomendamos contar con un constructor por defecto con al menos una visibilidad de paquete para la generacin de proxies en tiempo de ejecucin en Hibernate.

4.1.2. Proporcione una propiedad identificadora (opcional)Cat tiene una propiedad llamada id. Esta propiedad mapea a la columna de la llave principal de la tabla de la

base de datos. La propiedad podra llamarse de cualquier manera y su tipo podra haber sido cualquier tipo primitivo, cualquier tipo de "wrapper" primitivo, java.lang.String o java.util.Date. Si su tabla de base de datos heredada tiene claves compuestas, puede utilizar una clase definida por el usuario con propiedades de estos tipos (vea la seccin sobre identificadores compuestos ms adelante en este captulo). La propiedad identificadora es estrictamente opcional. Puede olvidarla y dejar que Hibernate siga internamente la pista de los identificadores del objeto. Sin embargo, no recomendamos que esto suceda. De hecho, algunas funcionalidades se encuentran disponibles slamente para clases que declaran una propiedad identificadora: Transitive reattachment for detached objects (cascade update or cascade merge) - see Seccin 10.11, Persistencia transitivaSession.saveOrUpdate() Session.merge()

Le recomendamos que declare propiedades identificadoras nombradas-consistentemente persistentes. y que utilice un tipo nulable (por ejemplo, no primitivo).

en clases

4.1.3. Prefiera las clases no finales (opcional)Un aspecto central de Hibernate, los proxies, dependen de que las clases persistentes sean no finales o de la implementacin de una interfaz que declare todos los mtodos pblicos. Con Hibernate puede persistir las clases final es que no implementen una interfaz. Sin embargo, no podr utilizar proxies para recuperacin perezosa de asociaciones, lo cual limitar sus opciones para afinar el rendimiento. Tambin debe evitar el declarar mtodos public final en las clases no-finales. Si quiere utilizar una clase con un mtodo public final , debe deshabilitar explcitamente el uso de proxies estableciendo lazy="false".

4.1.4. Declare mtodos de acceso y de modificacin para los campos persistentes (opcional)Cat declara mtodos de acceso para todos sus campos persistentes. Muchas otras herramientas ORM

persisten directamente variables de instancia. Es mejor proporcionar una indireccin entre el esquema relacional y las estructuras de datos internos de la clase. Por defecto, Hibernate persiste las propiedades del estilo JavaBeans, y reconoce los nombres de mtodo de la forma getFoo, isFoo y setFoo. De ser necesario, puede cambiarse al acceso directo a campos para propiedades especficas. No es necesario declarar pblicas las propiedades. Hibernate puede persistir una propiedad con un par get / set protected o private.

4.2. Implementacin de herenciaUna subclase tambin tiene que cumplir con la primera y la segunda regla. Hereda su propiedad identificadora de la superclase Cat . Por ejemplo:

41 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

package eg; public class DomesticCat extends Cat { private String name; public String getName() { return name; } protected void setName(String name) { this.name=name; } }

4.3. Implementando equals() y hashCode()Tiene que sobrescribir los mtodos equals() y hashCode() si: piensa poner instancias de clases persistentes en un Set (la forma recomendada de representar asociaciones multivaluadas); y piensa utilizar reasociacin de instancias separadas. Hibernate garantiza la equivalencia de identidad persistente (fila de base de datos) y de identidad Java slamente dentro del mbito de una sesin en particular. De modo que en el momento en que mezcla instancias recuperadas en sesiones diferentes, tiene que implementar equals() y hashCode() si desea tener una semntica significativa para Set s. La forma ms obvia es implementar equals()/hashCode() comparando el valor identificador de ambos objetos. Si el valor es el mismo, ambos deben ser la misma fila de la base de datos ya que son iguales. Si ambos son agregados a un Set , slo tendremos un elemento en el Set ). Desafortunadamente, no puede utilizar este enfoque con identificadores generados. Hibernate slo asignar valores identificadores a objetos que son persistentes; una instancia recin creada no tendr ningn valor identificador. Adems, si una instancia no se encuentra guardada y est actualmente en un Set , al guardarla se asignar un valor identificador al objeto. Si equals() y hashCode() estn basados en el valor identificador, el cdigo hash podra cambiar, rompiendo el contrato del Set . Consulte el sitio web de Hibernate y all encontrar una discusin completa sobre este problema. Este no es un problema de Hibernate, sino de la semntica normal de Java de identidad de objeto e igualdad. Le recomendamos implementar equals() y hashCode() utilizando igualdad de clave empresarial (Business key equality). Igualdad de clave empresarial significa que el mtodo equals() slamente compara las propiedades que forman la clave empresarial. Esta es una clave que podra identificar nuestra instancia en el mundo real (una clave candidata natural):public class Cat { ... public boolean equals(Object other) { if (this == other) return true; if ( !(other instanceof Cat) ) return false; final Cat cat = (Cat) other; if ( !cat.getLitterId().equals( getLitterId() ) ) return false; if ( !cat.getMother().equals( getMother() ) ) return false; return true; } public int hashCode() { int result; result = getMother().hashCode(); result = 29 * result + getLitterId(); return result; } }

A business key does not have to be as solid as a database primary key candidate (see Seccin 12.1.3, Consideracin de la identidad del objeto). Immutable or unique properties are usually good candidates for a business key.

4.4. Modelos dinmicosNotaThe following features are currently considered experimental and may change in the near

42 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

future.

Las entidades persistentes no necesariamente tienen que estar representadas como clases POJO o como objetos JavaBean en tiempo de ejecucin. Hibernate tambin soporta modelos dinmicos (utilizando Mapeos de Mapeos en tiempo de ejecucin) y la representacin de entidades como rboles de DOM4J. No escriba clases persistentes con este enfoque, slamente archivos de mapeo. By default, Hibernate works in normal POJO mode. You can set a default entity representation mode for a particular SessionFactory using the default_entity_mode configuration option (see Tabla 3.3, Propiedades de Configuracin de Hibernate). Los siguientes ejemplos demuestran la representacin utilizando Mapeos. Primero, en el archivo de mapeo tiene que declararse un entity-name en lugar de, o adems de un nombre de clase:

Aunque las asociaciones se declaran utilizando nombres de clase destino, el tipo destino de una asociacin puede ser adems una entidad dinmica en lugar de un POJO. Despus de establecer el modo de entidad predeterminado como dynamic-map para la SessionFactory, puede trabajar en tiempo de ejecucin con Mapeos de Mapeos:Session s = openSession(); Transaction tx = s.beginTransaction(); // Create a customer Map david = new HashMap(); david.put("name", "David"); // Create an organization Map foobar = new HashMap(); foobar.put("name", "Foobar Inc."); // Link both david.put("organization", foobar); // Save both s.save("Customer", david); s.save("Organization", foobar); tx.commit(); s.close();

Una de las ventajas principales de un mapeo dinmico es el rpido tiempo de entrega del prototipado sin la necesidad de implementar clases de entidad. Sin embargo, pierde el chequeo de tipos en tiempo de compilacin y muy probablemente tendr que tratar con muchas excepciones en tiempo de ejecucin. Gracias al mapeo de Hibernate, el esquema de base de datos se puede normalizar y volver slido, permitiendo aadir una implementacin apropiada del modelo de dominio ms adelante. Los modos de representacin de entidad se pueden establecer por Session:

43 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

Session dynamicSession = pojoSession.getSession(EntityMode.MAP); // Create a customer Map david = new HashMap(); david.put("name", "David"); dynamicSession.save("Customer", david); ... dynamicSession.flush(); dynamicSession.close() ... // Continue on pojoSession

Tenga en cuenta que la llamada a getSession() utilizando un EntityMode est en la API de Session, no en la deSessionFactory. De esta forma, la nueva Session comparte la conexin JDBC, la transaccin y otra informacin

de contexto. Esto significa que no tiene que llamar a flush() ni a close() en la Session secundaria, y tambin tiene que dejar el manejo de la transaccin y de la conexin a la unidad de trabajo primaria. More information about the XML representation capabilities can be found in Captulo 19, Mapeo XML.

4.5. Tuplizersorg.hibernate.tuple.Tuplizer y sus subinterfaces son las responsables de administrar una representacin en

particular de un dato, dadas las representaciones de org.hibernate.EntityMode. Si un dato dado se considera como una estructura de datos entonces un tuplizer es la cosa que sabe como crear tal estructura de datos y sabe como extraer e insertar valores en dicha estructura de datos. Por ejemplo, para el modo de entidad POJO, el tuplizer correspondiente sabe como crear el POJO por medio de su constructor. Tambin sabe como acceder a las propiedades POJO utilizando los accesores de propiedad definidos. Hay dos tipos altos de niveles de Tuplizers, representados por las interfaces

org.hibernate.tuple.entity.EntityTuplizer y org.hibernate.tuple.component.ComponentTuplizer. Los EntityTuplizers son

los responsables de administrar los contratos mencionados anteriormente en relacin con las entidades mientras que los ComponentTuplizers hacen lo mismo para los componentes. Los usuarios tambin pueden enchufar sus propios tuplizers. Tal vez necesite que una implementacinjava.util.Map diferente de java.util.HashMap se utilice en el modo de entidad de mapeo dinmico. O quizs

necesite definir una estrategia de generacin proxy diferente de la que se utiliza por defecto. Se pueden obtener ambas al definir una implementacin tuplizer personalizada. Las definiciones de los tuplizers se encuentran sujetas a la entidad o componente de mapeo que se supone que tienen que administrar. Regresando al ejemplo de nuestra entidad de cliente:

...

public class CustomMapTuplizerImpl extends org.hibernate.tuple.entity.DynamicMapEntityTuplizer { // override the buildInstantiator() method to plug in our custom map... protected final Instantiator buildInstantiator( org.hibernate.mapping.PersistentClass mappingInfo) { return new CustomMapInstantiator( mappingInfo ); } private static final class CustomMapInstantiator extends org.hibernate.tuple.DynamicMapInstantitor { // override the generateMap() method to return our custom map... protected final Map generateMap() { return new CustomMap(); } } }

4.6. EntityNameResolvers

44 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

La interfaz org.hibernate.EntityNameResolver es un contrato para resolver el nombre de la entidad de una instancia de entidad dada. La interfaz define un solo mtodo resolveEntityName , el cual se le pasa la instancia entidad y se espera que retorne el nombre de entidad apropriado (se permite nulo e indicara que el resolvedor no sabe cmo resolver el nombre de la entidad de la instancia de entidad dada). Generalmente hablando, un org.hibernate.EntityNameResolver ser ms til en el caso de modelos dinmicos. Un ejemplo puede ser el usar interfaces con proxis como su modelo de dominio. La suite de prueba de hibernate tiene un ejemplo de este estilo exacto de uso bajo el org.hibernate.test.dynamicentity.tuplizer2. Aqu est algo del cdigo de ese paquete para su ilustracin.

45 of 203

23/02/2011 04:37 p.m.

HIBERNATE - Persistencia relacional para Java idiomtico

http://docs.jboss.org/hibernate/core/3.5/reference/es-ES/html_single/#q...

/** * A very trivial JDK Proxy InvocationHandler implementation where we proxy an interface as * the domain model and simply store persistent state in an internal Map. This is an extremely * trivial example meant only for illustration. */ public final class DataProxyHandler implements InvocationHandler { private String entityName; private HashMap data = new HashMap(); public DataProxyHandler(String entityName, Serializable id) { this.entityName = entityName; data.put( "Id", id ); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String