From 9f527f632da23374c0200054367faf0237125422 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 19 Oct 2007 04:07:06 +0000 Subject: [PATCH] somehow this did not get deleted b4 git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14112 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../src/main/docbook/modules/architecture.xml | 279 -- .../docbook/modules/association_mapping.xml | 527 --- .../main/docbook/modules/basic_mapping.xml | 3222 ----------------- .../es-ES/src/main/docbook/modules/batch.xml | 192 - .../main/docbook/modules/best_practices.xml | 229 -- .../docbook/modules/collection_mapping.xml | 1241 ------- .../docbook/modules/component_mapping.xml | 403 --- .../main/docbook/modules/configuration.xml | 1761 --------- .../es-ES/src/main/docbook/modules/events.xml | 233 -- .../main/docbook/modules/example_mappings.xml | 654 ---- .../docbook/modules/example_parentchild.xml | 362 -- .../main/docbook/modules/example_weblog.xml | 429 --- .../src/main/docbook/modules/filters.xml | 130 - .../docbook/modules/inheritance_mapping.xml | 464 --- .../src/main/docbook/modules/performance.xml | 1334 ------- .../docbook/modules/persistent_classes.xml | 478 --- .../main/docbook/modules/query_criteria.xml | 431 --- .../src/main/docbook/modules/query_hql.xml | 1107 ------ .../src/main/docbook/modules/query_sql.xml | 477 --- .../src/main/docbook/modules/quickstart.xml | 666 ---- .../src/main/docbook/modules/session_api.xml | 1224 ------- .../main/docbook/modules/toolset_guide.xml | 459 --- .../src/main/docbook/modules/transactions.xml | 925 ----- .../src/main/docbook/modules/tutorial.xml | 1270 ------- .../es-ES/src/main/docbook/modules/xml.xml | 282 -- 25 files changed, 18779 deletions(-) delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/architecture.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/association_mapping.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/basic_mapping.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/batch.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/best_practices.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/collection_mapping.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/component_mapping.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/configuration.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/events.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/example_mappings.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/example_parentchild.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/example_weblog.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/filters.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/inheritance_mapping.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/performance.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/persistent_classes.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/query_criteria.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/query_hql.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/query_sql.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/quickstart.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/session_api.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/toolset_guide.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/transactions.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/tutorial.xml delete mode 100644 documentation/manual/es-ES/src/main/docbook/modules/xml.xml diff --git a/documentation/manual/es-ES/src/main/docbook/modules/architecture.xml b/documentation/manual/es-ES/src/main/docbook/modules/architecture.xml deleted file mode 100644 index b3688de633..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/architecture.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - Arquitectura - - - Visión General - - - Una visión a (muy) alto nivel de la arquitectura de Hibernate: - - - - - - - - - - - - - Este diagrama muestra a Hibernate usando la base de datos y los datos de - configuración para proveer servicios de persistencia (y objetos - persistentes) a la aplicación. - - - - Nos gustaría mostrar una vista más detallada de la arquitectura de tiempo - de ejecución. Desafortunadamente, Hibernate es flexible y soporta diferentes - enfoques. Mostraremos los dos extremos. En la arquitectura "sencilla", es la - aplicación la que provee su propias conexiones JDBC y gestiona sus propias - transacciones. Este enfoque usa un mínimo subconjunto de la API de Hibernate: - - - - - - - - - - - - - La arquitectura "full cream" abstrae a la aplicación de las APIs - de JDBC/JTA y deja que Hibernate se encargue de los detalles. - - - - - - - - - - - - - He aquí algunas definiciones de los objetos en los diagramas: - - - SessionFactory (org.hibernate.SessionFactory) - - - Caché threadsafe (inmutable) de mapeos compilados para - una sola base de datos. Es una fábrica de Session - y un cliente de ConnectionProvider. Opcionalmente, - puede mantener una caché (de segundo nivel) de datos reusables - entre transacciones, a un nivel de proceso o de cluster. - - - - - Session (org.hibernate.Session) - - - Objeto mono-hebra, de corta vida que representa una conversación - entre la aplicación y el almacenamiento persistente. Envuelve una - conexión JDBC. Es una fábrica de Transaction. - Mantiene una caché requerida (de primer nivel) de objetos persistentes, - usada mientras se navega el grafo de objetos o se recuperen objetos por - identificador. - - - - - Objetos y colecciones persistentes - - - Objetos de corta vida, mono-hebra conteniendo estado persistente y - funciónalidad de negocio. Estos pueden ser JavaBeans/POJOs - (Plain Old Java Objects, o sea, cualquier objeto Java), la única - cosa especial en ellos es que estan asociados actualmente con una - (y sólo una) Session. Tan pronto como la - Session sea cerrada, serán separados y - estarán libres para ser usados en cualquier capa de aplicación. - (por ejemplo, directamente como objetos de transferencia de datos hacia - y desde la capa de presentación). - - - - - Objetos y colecciones transitorios y separados - - - Instancias de clases persistentes que no estan acutualmente asociadas - con una Session. Pueden haber sido instanciadas por - la aplicación y (aún) no haber sido hechas persistentes, - o pueden haber sido instanciadas por una Session cerrada. - - - - - Transaction (org.hibernate.Transaction) - - - (Opcional) Un objeto de corta vida, mono-hebra, usado por la aplicación - para especificar unidades atómicas de trabajo. Abstrae a la aplicación - de las subyacentes transacciones JDBC, JTA o CORBA. En algunos casos, una - Session puede extenderse sobre varias Transactions. - Sin embargo, la demarcación de la transacción, ya sea usando la API - subyacente o Transaction, nunca es opcional! - - - - - ConnectionProvider (org.hibernate.connection.ConnectionProvider) - - - (Opcional) Una fábrica (y pool) de conexiones JDBC. Abstrae a la aplicación - del Datasource o DriverManager subyacente. - No se expone a la aplicación, pero puede ser extendido/implementado por - el desarrollador. - - - - - TransactionFactory (org.hibernate.TransactionFactory) - - - (Opcional) Una fábrica de instancias de Transaction. - No se expone a la aplicación, pero puede ser extendido/implementado por - el desarrollador. - - - - - Interfaces de Extensión - - - Hibernate ofrece muchas interfaces de extensión opcional que puedes - implementar para modificar a medida el comportamiento de tu capa de persistencia. - Para más detalles, mira la documentación de la API. - - - - - - - - Dada una arquitectura "sencilla", la aplicación pasa por alto las APIs - de Transaction/TransactionFactory y/o - ConnectionProvider, para hablar directamente a JTA o JDBC. - - - - - Estados de instancia - - Una instancia de una clase persistente puede estar en uno de tres estados - diferentes, definidos respecto de su contexto de persistencia. - El objeto Session de Hibernate es el contexto de persistencia: - - - - - transitorio - - - La instancia no está y nunca estuvo asociada con - un contexto de persistencia. No tiene identidad persistente - (valor de clave primaria). - - - - - persistente - - - La instancia está actualmente asociada con un - contexto de persistencia. Tiene una identidad persistente - (valor de clave primaria) y, quizás, una fila - correspondiente en la base de datos. Para un contexto de - persistencia en particular, Hibernate garantiza - que la identidad persistente es equivalente a la identidad - Java (localización en memoria del objeto). - - - - - separado - - - La instancia estuvo una vez asociada con un contexto - de persistencia, pero ese contexto fue cerrado, o la - instancia fue serializada a otro proceso. Tiene una - identidad persistente y, quizás, una fila correspondiente - en la base de datos. Para las instancias separadas, - Hibernate no establece ninguna garantía sobre - la relación entre identidad persistente e identidad Java. - - - - - - - - Integración JMX - - - JMX es el estándar J2EE para la gestión de componentes Java. Hibernate - puede ser gestionado por medio de un servicio estándar JMX. - Proveemos una implementación de MBean en la distribución, - org.hibernate.jmx.HibernateService. - - - - Para ejemplo de cómo desplegar Hibernate como un servicio JMX en un Servidor - de Aplicaciones JBoss, por favor, mira la Guía del Usuario de JBoss. - En JBoss AS, tienes además estos beneficios si despliegas usando JMX: - - - - - - Gestión de Sesión: El ciclo de vida de la Session - de Hibernate puede estar automáticamente ligado al ámbito de una transacción - JTA. Esto significa que ya no tienes que abrir ni cerrar la Session manualmente, - esto pasa a ser trabajo de un interceptor EJB de JBoss. Además tampoco tienes - que preocuparte más de la demarcación de la transacción (a menos que - que quieras escribir una capa de persitencia portable, por supuesto, usa la API de - Transaction de Hibernate para esto). Para acceder a una - Session llama al HibernateContext. - - - - - Despliegue de HAR: Usualmente despliegas el servicio JMX de Hibernate - usando un descriptor de despliegue de servicio de JBoss (en un fichero EAR y/o SAR), que soporta - todas las opciones de configuración usuales de una SessionFactory de - Hibernate. Sin embargo, todavía tienes que nombrar todos tus ficheros de mapeo en el - descriptor de despliegue. Si decides usar el depliegue de HAR opcional, JBoss detectará - automáticamente todos los ficheros de mapeo en tu fichero HAR. - - - - - - Para más información sobre estas opciones, consulta la - Guía de Usuario del JBoss AS. - - - - Otra funcionalidad disponible como un servicio JMX son las estadísticas en - tiempo de ejecución de Hibernate. Mira . - - - - - Soporte JCA: - - Hiberate puede además ser configurado como un conector JCA. Por favor mira el - sitio web para más detalles. Por favor ten en cuenta que el soporte de JCA - de Hibernate está aún considerado experimental. - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/association_mapping.xml b/documentation/manual/es-ES/src/main/docbook/modules/association_mapping.xml deleted file mode 100644 index 80a543664e..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/association_mapping.xml +++ /dev/null @@ -1,527 +0,0 @@ - - - Mapeos de Asociación - - - Introducción - - - Los mapeos de asociación son frecuentemente las cosas mas difíciles - de hacer correctamente. En esta sección iremos a través de los casos - canónicos uno a uno, comenzando con los mapeos unidireccionales, y considerando - luego los casos bidireccionales. Usaremos Person y Address - en todos los ejemplos. - - - - Clasificaremos las asociaciones por cuanto mapeen o no a una tabla - de unión interviniente, y por su multiplicidad. - - - - Las claves foráneas que aceptan valores nulos (en adelante, nullables) - no son consideradas una buena práctica en el modelado tradicional de datos, - así que todos nuestros ejemplos usan claves foráneas no nullables. - Esto no es un requerimiento de Hibernate, y todos los mapeos funcionarán - si quitas las restricciones de nulabilidad. - - - - - - Asociaciones Unidireccionales - - - muchos a uno - - - Una asociación unidireccional muchos-a-uno es el tipo - más común de asociaciones unidireccionales. - - - - - - - - - - - - - -]]> - - - - - - uno a uno - - - Una asociación unidireccional uno-a-uno en una clave primaria - es casi idéntica. La única diferencia es la restricción de unicidad - de la columna. - - - - - - - - - - - - - -]]> - - - - Usualmente, una asociación unidireccional uno-a-uno en una - clave primaria usa un generador de id especial. (Observa que hemos - invertido el sentido de la asociación en este ejemplo). - - - - - - - - - - - - person - - - -]]> - - - - - - uno a muchos - - - Una asociación unidireccional uno-a-muchos en una clave foránea - es un caso muy inusual, y realmente no está recomendada. - - - - - - - - - - - - - - - - -]]> - - - - Creemos que es mejor usar una tabla de unión para este tipo de asociación. - - - - - - - - Asociaciones unidireccionales con tablas de unión - - - uno a muchos - - - Una asociación unidireccional uno-a-muchos en una tabla de unión - es más preferible. Observa que especificando unique="true", hemos - cambiado la multiplicidad de muchos-a-muchos a uno-a-muchos. - - - - - - - - - - - - - - - - -]]> - - - - - - muchos a uno - - - Una asociación unidireccional muchos-a-uno en una tabla de unión - es bastante común cuando la asociación es opcional. - - - - - - - - - - - - - - - - -]]> - - - - - - uno a uno - - - Una asociación unidireccional uno-a-uno en una tabla de unión - es inusual en extremo, pero posible. - - - - - - - - - - - - - - - - -]]> - - - - - - muchos a muchos - - - Finalmente, tenemos una asociación unidireccional muchos-a-muchos - - - - - - - - - - - - - - - - -]]> - - - - - - - - Asociaciones Bidireccionales - - - uno a muchos / muchos a uno - - - Una asociación bidireccional muchos-a-uno es - el tipo más común de asociación. (Esta es la relación - estándar padre/hijo.) - - - - - - - - - - - - - - - - - -]]> - - - - - - - uno a uno - - - Una asociación bidireccional uno-a-uno en una clave foránea - es bastante común. - - - - - - - - - - - - - - -]]> - - - - Una asociación bidireccional uno-a-uno en una clave primaria - usa el generador de id especial. - - - - - - - - - - - - - person - - - -]]> - - - - - - - - Asociaciones bidireccionales con tablas de unión - - - uno a muchos / muchos a uno - - - Una asociación bidireccional uno-a-muchos en una tabla de unión. - Observa que el inverse="true" puede ir a cualquier lado de la asociación, - en la colección, o en la unión. - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - uno a uno - - - Una asociación bidireccional uno-a-uno en una tabla de unión - es inusual en extremo, pero posible. - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - muchos a muchos - - - Finalmente, tenemos una asociación bidireccional muchos-a-muchos. - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/basic_mapping.xml b/documentation/manual/es-ES/src/main/docbook/modules/basic_mapping.xml deleted file mode 100644 index 13680bd9ba..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/basic_mapping.xml +++ /dev/null @@ -1,3222 +0,0 @@ - - Mapeo O/R Básico - - - Declaración de mapeo - - - Los mapeos objeto/relacional se definen usualmente en un documento XML. - El documento de mapeo está diseñado para ser leíble y - editable a mano. El lenguaje de mapeo es Java-céntrico, o sea que los - mapeos se construyen alrededor de declaraciones de clases persistentes, - no declaraciones de tablas. - - - - Observa que, incluso aunque muchos usuarios de Hibernate eligen escribir el - XML a mano, existe una cantidad de herramientas para generar el documento de - mapeo, incluyendo XDoclet, Middlegen y AndroMDA. - - - - Comencemos por un mapeo de ejemplo: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Discutiremos ahora el contenido del documento de mapeo. Describiremos sólo los - elementos y atributos que son usados por Hibernate en tiempo de ejecución. El - documento de mapeo contiene además algunos atributos y elementos extra opcionales - que afectan los esquemas de base de datos exportados por la herramienta de exportación - de esquemas. (Por ejemplo, el atributo not-null.) - - - - - - Doctype - - - Todos los mapeos XML deben declarar el doctype mostrado. El DTD actual puede - ser encontrado en el URL mencionado arriba, en el directorio - hibernate-x.x.x/src/org/hibernate, o en hibernate3.jar. - Hibernate siempre buscará el DTD primero en el classpath. Si experimentas - búsquedas del DTD usando una conexión de Internet, chequea tu declaración - de DTD contra la contenida en el classpath. - - - - - hibernate-mapping - - - Este elemento tiene muchos atributos opcionales. Los atributos schema - y catalog especifican que las tablas a las que se refiere en el mapeo - pertenecen al esquema y/o catálogo mencionado(s). De especificarse, los nombres de - tablas serán cualificados por el nombre de esquema y catálogo dados. - De omitirse, los nombres de tablas no serán cualificados. El atributo - default-cascade especifica qué estilo de cascada debe asumirse - para las propiedades y colecciones que no especifican un atributo cascade. - El atributo auto-import nos permite usar nombres de clase sin cualificar - en el lenguaje de consulta, por defecto. - - - - - - - - - - - - - ]]> - - - - schema (opcional): El nombre de un esquema de la base de datos. - - - - - catalog (opcional): El nombre de un catálogo de la base de datos. - - - - - default-cascade (opcional - por defecto a none): - Un estilo de cascada por defecto. - - - - - default-access (opcional - por defecto a property): - La estrategia que Hibernate debe usar para acceder a todas las propiedades. - Puede ser una implementación personalizada de PropertyAccessor. - - - - - default-lazy (opcional - por defecto a true): - El valor por defecto para los atributos lazy de mapeos de clase - y colleción no especificados. - - - - - auto-import (opcional - por defecto a true): - Especifica si podemos usar nombres de clases no cualificados (de clases en este mapeo) - en el lenguaje de consulta. - - - - - package (opcional): Especifica un prefijo de paquete a asumir - para los nombres no cualificados de clase en el documento de mapeo. - - - - - - - Si tienes dos clases persistentes con el mismo nombre (sin cualificar), debes establecer - auto-import="false". Hibernate lanzará una excepción si - intentas asignar dos clases al mismo nombre "importado". - - - - Observa que el elemento hibernate-mapping te permite anidar - muchos mapeos <class> persistentes, como se muestra arriba. - Sin embargo, es una buena práctica (y se espera de algunas herramientas) mapear - sólo a una sola clase persistente (o a una sola jerarquía de clases) en - un fichero de mapeo y nombrarlo después de la superclase persistente; - por ejemplo, Cat.hbm.xml, Dog.hbm.xml, - o, si se usa herencia, Animal.hbm.xml. - - - - - - class - - - Puedes declarar una clase persistente usando el elemento class: - - - - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - - - name (opcional): El nombre completamente cualificado de la clase - Java persistente (o interface). Si este atributo es omitido, se asume que el mapeo - es para una entidad non-POJO. - - - - - table (opcional - por defecto al nombre no cualificado de la clase): - El nombre de su tabla en base de datos. - - - - - discriminator-value (opcional - por defecto al nombre de la clase): - Un valor que distingue subclases individuales, usado para el comportamiento - polimórfico. Los valores aceptables incluyen null - y not null. - - - - - mutable (opcional, por defecto a true): - Especifica que las instancias de la clase (no) son mutables. - - - - - schema (opcional): Sobreescribe el nombre de esquema especificado - por el elemento raíz <hibernate-mapping>. - - - - - catalog (opcional): Sobreescribe el nombre de catálogo - especificado por el elemento raíz <hibernate-mapping>. - - - - - proxy (opcional): Especifica una interface a usar para proxies - de inicialización perezosa. Puedes especificar el nombre mismo de la clase. - - - - - dynamic-update (opcional, por defecto a false): - Especifica que el SQL UPDATE debe ser generado en tiempo de - ejecución y contener solamente aquellas columnas cuyo valor haya cambiado. - - - - - dynamic-insert (opcional, por defecto a false): - Especifica que el SQL INSERT debe ser generado en tiempo de - ejecución y contener solamente aquellas columnas cuyo valores no son nulos. - - - - - select-before-update (opcional, por defecto a false): - Especifica que Hibernate nunca debe realizar un SQL UPDATE - a menos que se tenga certeza que un objeto haya sido modificado realmente. - En ciertos casos, (realmente, sólo cuando un objeto transitorio ha sido asociado - con una sesión nueva usando update()), esto significa que Hibernate - realizará una SQL SELECT extra para determinar si un - UPDATE es realmente requerido. - - - - - polymorphism (opcional, por defecto a implicit): - Determina si se usa polimorfismo de consulta implícito o explícito. - - - - - where (opcional) especifica una condición SQL WHERE - arbitraria paraa ser usada al recuperar objetos de esta clase. - - - - - persister (opcional): Especifica un ClassPersister - personalizado. - - - - - batch-size (opcional, por defecto a 1) - especifica un "tamaño de lote" para traer instancias de esta clase por - identificador. - - - - - optimistic-lock (opcional, por defecto a version): - Determina la estrategia optimista de bloqueo. - - - - - lazy (opcional): - La recuperación perezosa puede ser deshabilitada por completo estableciendo - lazy="false". - - - - - entity-name (opcional): Hibernate3 permite que una clase sea - mapeada varias veces (potencialmente a tablas diferentes), y permite que los mapeos - de entidad sean representados por Maps o XML al nivel de Java. En estos casos, - debes proveer un nombre explícito arbitrario para la entidad. - Para más información, mira - y . - - - - - check (opcional): Una expresión SQL usada para generar - una restricción check multi-fila para la generación - automática de esquema. - - - - - rowid (opcional): Hibernate puede usar los llamados ROWIDs en las - bases de datos que los soporten. Por ejemplo, en Oracle, Hibernate puede usar la columna - extra rowid para actualizaciones rápidas si estableces esta - opción a rowid. Un ROWID es un detalle de implementación - y representa la posición física de la tupla almacenada. - - - - - subselect (opcional): Mapea una entidad inmutable y de sólo - lectura a una subselect de base de datos. Es útil si quieres tener una vista - en vez de una tabla base, pero no tienes vistas. Mira debajo para más información. - - - - - abstract (opcional): Usado para marcar superclases abstractas en - jerarquías <union-subclass>. - - - - - - - Es perfectamente aceptable que la clase persistente mencionada sea una interface. - Entonces declararías clases que implementan esa interface usando el elemento - <subclass>. Puedes persistir cualquier clase interna - estática. Debes especificar el nombre de la clase usando la forma - estándar. Por ejemplo, eg.Foo$Bar. - - - - Las clases inmutables, mutable="false", no pueden ser actualizadas o - borradas por la aplicación. Esto permite a Hibernate hacer ciertas optimizaciones - menores de rendimiento. - - - - El atributo opcional proxy habilita la inicialización postergada - de instancias persistentes de la clase. Hibernate inicialmente retornará proxies - CGLIB que implementan la interface mencionada. El objeto persistente real será - cargado cuando se invoque un método del proxy. Mira "Proxies para Inicialización - Postergada" debajo. - - - - Por polimorfismo implícito se entiende que las instancias de la clase - serán devueltas por una consulta que mencione cualquier superclase, o interface implementada, - o la clase misma; y que las instancias de cualquier subclase de la clase serán devueltas - por una clase que mencione a la clase en sí. - Por polimorfismo explícito se entiende que instancias de la clase - serán devueltas sólo por consultas que mencionen explícitamente la clase; - y que las consultas que mencionen la clase devolverán sólo instancias de subclases - mapeadas dentro de esta declaración <class> como una - <subclass> o <joined-subclass>. - Para la mayoría de los propósitos el defecto, - polymorphism="implicit", resulta apropiado. - El polimorfismo explícito es útil cuando dos clases diferentes están - mapeadas a la misma tabla (esto permite tener una clase "liviana" que contenga un subconjunto - de columnas de la tabla). - - - - El atributo persister te permite personalizar la estrategia de persistencia - para la clase. Puedes, por ejemplo, especificar tu propia subclase de - org.hibernate.persister.EntityPersister o incluso puedes proveer una implementación - completamente nueva de la interface org.hibernate.persister.ClassPersister que implemente - la persistencia por medio, por ejemplo, de llamadas a procedimientos almacenados, serialización a - ficheros planos o LDAP. Para un ejemplo simple (de persistencia a una Hashtable) mira - org.hibernate.test.CustomPersister. - - - - Observa que los valores de dynamic-update y dynamic-insert - no son heredados por las subclases y por lo tanto deben especificarse en los elementos - <subclass> o <joined-subclass>. - Estos ajustes pueden incrementar el rendimiento en algunos casos, pero podrían mermarlo en otros. - Ten juicio en su uso. - - - - Generalmente el uso de select-before-update disminuirá el rendimiento. - Es muy útil prevenir que se llame innecesariamente a un disparador de actualización de - base de datos al volver a unir un grafo de instancias separadas a una Session. - - - - Si habilitas dynamic-update, tendrás opción de estrategias - de bloqueo optimistas: - - - - - version chequea las columnas de versión/timestamp - - - - - all chequea todas las columnas - - - - - dirty chequea las columnas modificadas, permitiendo algunas - actualizaciones concurrentes - - - - - none no usa bloqueo optimista - - - - - Recomendamos muy fuertemente que uses columnas de - versión/timestamp para bloqueo optimista con Hibernate. Esta es la estrategia - óptima con respecto al rendimiento y es la única estrategia que maneja - correctamente las modificaciones hechas a las instancias separadas. - (por ejemplo, cuando se usa Session.merge()). - - - - Para un mapeo de Hibernate, no hay diferencia entre una vista y una tabla base. - Como se supone esto es transparente a nivel de base de datos (observa que algunos - DBMS no soportan correctamente las vistas, especialmente con las actualizaciones). - A veces quieres usar una vista, pero no puedes crear una en la base de datos - (por ejemplo, con un esquema heredado). En este caso, puedes mapear una entidad inmutable - de sólo lectura a una expresión de subconsulta SQL dada. - - - - - select item.name, max(bid.amount), count(*) - from item - join bid on bid.item_id = item.id - group by item.name - - - - - ... -]]> - - - Declara las tablas con las que sincronizar esta entidad, asegurando que el auto-flush - ocurre correctamente, y que las consultas contra la entidad derivada no devuelven datos - desactualizados. El <subselect> está disponible tanto - como un atributo o como un elemento anidado de mapeo. - - - - - - id - - - Las clases mapeadas deben declarar la columna de clave primaria de la tabla - de la base de datos. En la mayoría de los casos tendrá también una propiedad - estilo Javabeans que tenga el identificador único de una instancia. El elemento - <id> define el mapeo de esa propiedad a la columna de clave primaria. - - - - - - - - - - - - - -]]> - - - - name (opcional): El nombre de la propiedad del indentificador. - - - - - type (opcional): Un nombre que indica el tipo Hibernate. - - - - - column (opcional - por defecto al nombre de la propiedad): - El nombre de la columna de clave primaria. - - - - - unsaved-value (opcional - por defecto al valor "sensible"): - Una valor de la propiedad identificadora que indica que una instancia está - recién instanciada (sin salvar), distinguiéndola de instancias separadas - que fueran salvadas o cargadas en una sesión previa. - - - - - access (opcional - por defecto a property): - La estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - - - Si se omite el atributo name, se asume que la clase no tiene propiedad - identificadora. - - - - El atributo unsaved-value es importante! Si la propiedad identificadora de tu - clase no tiene por defecto el valor por defecto normal de Java (null o cero), entonces debes especificar - el valor por defecto real. - - - - Hay una declaración <composite-id> alternativa para permitir acceso - a datos heredados con claves compuestas. Desalentamos fuertemente su uso para cualquier otra cosa. - - - - Generator - - - El elemento hijo opcional <generator> nombra una clase Java - usada en generar identificadores únicos para instancias de la clase persistente. - De requerirse algún parámetro para configurar o inicializar la instancia del generador, - se pasa usando el elemento <param>. - - - - - uid_table - next_hi_value_column - -]]> - - - Todos los generadores implementan la interface org.hibernate.id.IdentifierGenerator. - Esta es una interface muy simple; algunas aplicaciones pueden escoger proveer sus propias - implementaciones especializadas. Sin embargo, Hibernate provee un rango de implementaciones - prefabricadas. Hay nombres alias de atajo para los generadores prefabricados: - - - increment - - - genera indentificadores de tipo long, short o - int que sólo son únicos cuando ningún otro proceso - está insertando datos en la misma tabla. No usar en un cluster. - - - - - identity - - - soporta columnas de identidad en DB2, MySQL, MS SQL Server, Sybase y - HypersonicSQL. El identificador devuelto es de tipo long, - short o int. - - - - - sequence - - - usa una secuencia en DB2, PostgreSQL, Oracle, SAP DB, McKoi o un generador - en Interbase. El identificador devuelto es de tipo long, - short o int. - - - - - hilo - - - usa un algoritmo alto/bajo para generar eficientemente identificadores de tipo - long, short o int, - dada una tabla y columna como fuente de valores altos (por defecto - hibernate_unique_key y next_hi respectivamente). - El algoritmo alto/bajo genera identificadores que son únicos sólo para una - base de datos particular. - - - - - seqhilo - - - usa un algoritmo alto/bajo para generar eficientemente identificadores de tipo - long, short o int, - dada una secuencia de base de datos. - - - - - uuid - - - usa un algoritmo UUID de 128 bits para generar identificadore de tipo - cadena, únicos en una ref (se usa la direccón IP). El UUID - se codifica como una cadena hexadecimal de 32 dígitos de largo. - - - - - guid - - - usa una cadena GUID generada por base de datos en MS SQL Server y MySQL. - - - - - native - - - selecciona identity, sequence o - hilo dependiendo de las capacidades de la base de datos - subyacente. - - - - - assigned - - - deja a la aplicación asignar un identificador al objeto antes - de que se llame a save(). Esta es la estrategia - por defecto si no se especifica un elemento <generator>. - - - - - select - - - recupera una clave primaria asignada por un disparador de base de datos - seleccionando la fila por alguna clave única y recuperando el valor de - la clave primaria. - - - - - foreign - - - usa el identificador de otro objeto asociado. Generalmente usado en conjuncón - a una asociacón de clave primaria <uno-a-uno> - - - - - - - - - - Algoritmo alto/bajo - - Los generadores hilo y seqhilo proveen dos implementaciones - alternativas del algoritmo alto/bajo, un enfoque favorito en generación de identificadores. - La primera implementación requiere de una tabla "especial" de base de datos para tener el siguiente - valor "alto" disponible. - La segunda usa una secuencia del estilo de Oracle (donde se soporte). - - - - - hi_value - next_value - 100 - -]]> - - - - hi_value - 100 - -]]> - - - Desafortunadamente, no puedes usar hilo cuando le proveas tu propia - Connection a Hibernate. Cuando Hibernate está usando un datasource - del servidor de aplicaciones para obtener conexiones alistadas con JTA, debes configurar - correctamente el hibernate.transaction.manager_lookup_class. - - - - - Algoritmo UUID - - El UUID contiene: la dirección IP, el instante de arranque de la JVM - (con una precisión de un cuarto de segundo), el tiempo de sistema y un valor - de contador (único en la JVM). No es posible obtener una dirección MAC o - una dirección de memoria desde código Java, así que esto es lo mejor - que podemos hacer sin usar JNI. - - - - - Columnas de identidad y secuencias - - Para las bases de datos que soportan columnas de identidad (DB2, MySQL, Sybase, MS SQL), - puedes usar generación de claves identity. Para las bases de datos - que soportan secuencias (DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB) puedes usar la generación - de claves del estilo sequence. Ambas estrategias requieren dos consultas SQL - para insertar un nuevo objeto. - - - - - person_id_sequence - -]]> - - - -]]> - - - Para desarrollos multiplataforma, la estrategia native - eiligirá de entre las estrategias identity, - sequence y hilo, dependiendo de las capacidades - de la base de datos subyacentes. - - - - - Identificadores asignados - - Si quieres que la aplicación asigne los identificadores (en contraposición - a que los genere Hibernate), puedes usar el generador assigned. - Este generador especial usará el valor identificador ya asignado a la - propiedad identificadora del objeto. Este generador se usa cuandola clave primaria es - una clave natural en vez de una clave sustituta. Este es el comportamiento por defecto si - no especificas un elemento <generator>. - - - - Elegir el generador assigned hace que Hibernate use - unsaved-value="undefined", forzando a Hibernate a ir - a la base de datos para determinar si una instancia es transitoria o separada, - a menos que haya una propiedad de versión o timestamp, o que tu definas - Interceptor.isUnsaved(). - - - - - Claves primarias asignadas por disparadores - - Para esquemas heredados solamente (Hibernate no genera DDL con disparadores). - - - - - socialSecurityNumber - -]]> - - - En el ejemplo de arriba, hay una propiedad ánica llamada - socialSecurityNumber definida por la clase, como - una clave natural, y una clave sustituta llamada person_id - cuyo valor es generado por un disparador. - - - - - - - - composite-id - - - - - - ...... -]]> - - - Para una tabla con clave compuesta, puedes mapear múltiples propiedades - de la clase como propiedades identificadoras. El elemento <composite-id> - acepta los mapeos de propiedad <key-property> y - los mapeos <key-many-to-one> como elementos hijo. - - - - - -]]> - - - Tu clase persistente debe sobreescribir equals() - y hashCode() para implementar igualdad de identificador compuesto. - Debe también implementar Serializable. - - - - Desafortunadamente, este enfoque de identificadores compuestos significa que un objeto - persistente es su propio identificador. No existe otra "asa" conveniente más que el - objeto mismo. Debes instanciar una instancia de la clase misma y poblar sus propiedades - identificadoras antes que puedas load() el estado persistente asociado - a una clave compuesta. Describiremos un enfoque mucho más conveniente donde el identificador - compuesto está implementado como una clase separada en . - Los atributos descriptos debajo solamente se aplican a este enfoque alternativo: - - - - - - name (opcional): Una propiedad de tipo componente que tiene el identificador - compuesto (ver siguiente sección). - - - - - class (opcional - por defecto al tipo de la propiedad determinado - por reflección): La clase del componente usado como identificador compuesto (ver siguiente sección). - - - - - unsaved-value (opcional - por defecto a undefined): - Indica que las instancias transitorias deben ser consideradas como recién instanciadas, - si se establece a any, o separadas, si se establece a none. - Lo mejor - - Indicates that transient instances should be considered newly instantiated, if set - to any, or detached, if set to none. - Lo mejor en todos los casos es dejar el valor por defecto. - - - - - - - - discriminator - - - El elemento <discriminator> es requerido para la persistencia - polimórfica usando la estrategia de mapeo de tabla-por-jerarquía-de-clases y - declara una columna discriminadora de la tabla. La columna discriminidora contiene valores - de marca que le dicen a la capa de persistencia qué subclase instanciar para una fila - en particular. Un conjunto restringido de tipos puede ser usado: - string, character, integer, - byte, short, boolean, - yes_no, true_false. - - - - - - - - - - - ]]> - - - - column (opcional - por defecto a class) el - nombre de la columna discriminadora. - - - - - type (opcional - por defecto a string) un - nombre que indique el tipo Hibernate - - - - - force (optconal - por defecto a false) - "fuerza" a Hibernate a especificar valores discriminadores permitidos incluso - cuando se recuperan todas las instancias de la clase raíz. - - - - - insert (opcional - por defecto a true) - establezca este a false si tu columna discriminadora es - también parte de un identificador mapeado compuesto. (Le dice a Hibernate - que no incluya la columna en los SQL INSERTs.) - - - - - formula (opcional) una expresión SQL arbitraria que - es ejecutada cuando un tipo tenga que ser evaluado. Permite dicriminación - basada en el contenido. - - - - - - - Los valores reales de la columna discriminadora están especificados por - el atributo discriminator-value de los elementos - <class> y <subclass>. - - - - El atributo force es (sólo) útil si la tabla contiene - filas con valores discriminadores "extra" que no están mapeados a la clase - persistente. Generalmente este no es el caso. - - - - Usando el atributo formula puedes declarar una expresión SQL - arbitraria que será usada para evaluar el tipo de una fila: - - - ]]> - - - - - version (opcional) - - - El elemento <version> es opcional e indica que la - tabla contiene datos versionados. Esto es particularmente útil si planeas - usar transacciones largas (ver debajo). - - - - - - - - - - - ]]> - - - - column (opcional - por defecto al nombre de la propiedad): El nombre - de la columna que tiene el número de versión. - - - - - name: El nombre de una propiedad de la clase persistente. - - - - - type (opcional - por defecto a integer): - El tipo del nú.mero de vesión. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - unsaved-value (opcional - por defecto a undefined): - Un valor de la propiedad de versión que indica que una instancia está - recién instanciada (sin guardar), distinguiéndola de instancias - separadas que fueran guardadas o cargadas en una sesión previa. - (undefined especifica que debe usarse el valor de la - propiedad identificadora.) - - - - - - - Los números de versión deben ser de tipo long, - integer, short, timestamp o - calendar de Hibernate. - - - - Una propiedad de versión o timestamp nunca debe ser nula para una instancia - separada, de modo que Hibernate detectará cualquier instancia con una versión - o timestamp nulo como transitoria, sin importar qué otras estrategias - unsaved-value se hayan especificado. - Declarar una propiedad de versón o timestamp nulable es una forma - fácil de evitar cualquier problema con la re-unión transitiva en Hibernate, - especialmente útil para que usa identificadores asignados o claves compuestas! - - - - - timestamp (opcional) - - - El elemento opcional <timestamp> indica que la tabla contiene - datos con sellos de tiempo. Esto esta concebido como una alternativa al versionado. - Los timestamps (sellos de tiempo) son por su naturaleza una implementación menos - segura de bloqueo optimista. Sin embrago, a veces la aplicación puede usar los - timestamps en otras formas. - - - - - - - - - - ]]> - - - - column (opcional - por defecto al nombre de la propiedad): El nombre - de una columna que tiene el timestamp. - - - - - name: El nombre de una propiedad del estilo JavaBeans de tipo - Java Date o Timestamp de la clase persistente. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - unsaved-value (opcional - por defecto a null): - Un valor de propiedad de versión que indica que una instancia está - recién instanciada (sin guardar), distinguiéndola de instancias separadas - que hayan sido guardadas o cargadas en una sesión previa. - (undefined especifica que debe usarse el valor de la propiedad - identificadora.) - - - - - - - Note that <timestamp> is equivalent to - <version type="timestamp">. - - - - - - property - - - El elemento <property> declara una propiedad persistente estilo - JavaBean de la clase. - - - - - - - - - - - - - - - - - - - ]]> - - - - name: el nombre de la propiedad, con la letra inicial - en minúsculas. - - - - - column (opcional - por defecto al nombre de la propiedad): el nombre - de la columna de tabla de base de datos mapeada. Esto puede también ser especificado - con elemento(s) <column> anidado(s). - - - - - type (opcional): un nombre que indica el nobre Hibernate. - - - - - update, insert (opcional - por defecto a true) : - especifica que las columnas mapeadas deben ser incluídas en las sentencias SQL - UPDATE y/o INSERT . Especificando ambas a - false permite una propiedad "derivada" cuyo valor es inicializado desde - alguna otra propiedad que mapee a la misma columna (o columnas) o por un disparador u otra - aplicación. - - - - - formula (opcional): una expresión SQL que define el valor - para una propiedad computada. Las propiedades computadas no tienen - una columna mapeada propia. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - lazy (opcional - por defecto a false): Especifica - que esta propiedad debe ser traída perezosamente cuando la variable de instancia - sea accedida por primera vez (requiere instrumentación en tiempo de compilación). - - - - - unique (opcional): Habilita la generació DDL de una restricción - de unicidad para las columnas. Además, permite que ésta sea un blanco objetivo de - una property-ref. - - - - - not-null (opcional): Habilita la generació DDL de una restricción - de nulabilidad para las columnas. - - - - - optimistic-lock (opcional - por defecto a true): - Especifica que las actualizaciones a esta propiedad requieran o no de la obtención - de un bloqueo optimista. En otras palabras, determina si debe ocurrir un incremento de versión - cuando la propiedad este sucia (desactualizada). - - - - - - - typename puede ser: - - - - - - El nombre de un tipo básico Hibernate (por ejemplo, integer, string, character, - date, timestamp, float, binary, serializable, object, blob). - - - - - El nombre de una clase Java de tipo básico (por ejemplo, int, float, - char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob). - - - - - El nombre de una clase Java serializable. - - - - - El nombre de un tipo personalizado (por ejemplo, com.illflow.type.MyCustomType). - - - - - - Si no especificas un tipo, Hibernate usará reflección sobre la - propiedad mencionada para deducir el tipo Hibernate correcto. Hibernate intentará - interpretar el nombre de la clase de retorno del getter de la propiedad usando las reglas - 2, 3 y 4 en ese orden. Sin embargo, esto no siempre suficiente. En ciertos casos, necesitarás - aún el atributo type. (Por ejemplo, para distinguir entre - Hibernate.DATE y Hibernate.TIMESTAMP, - o especificar un tipo personalizado.) - - - - El atributo access te deja controlar cómo Hibernate - accederá a la propiedad en tiempo de ejecución. Por defecto, Hibernate - llamará al par de getter/setter de la propiedad. Si especificas - access="field", Hibernate se saltará el par get/set y - accederá al campo directamente usando reflección. Puedes especificar tu - propia estrategia de acceso a la propiedad mencionando una clase que implemente - la interface org.hibernate.property.PropertyAccessor. - - - - Una aspecto especialmente poderoso son las propiedades derivadas. Estas propiedades - son por definición de sólo lectura, el valor de la propiedad es computado - en tiempo de carga. Tu declaras la computación como una expresión SQL, - y ésta se traduce a cláusula de subconsulta SELECT - en la consulta SQL que cargue una instancia: - - - ]]> - - - Observa que puedes referenciar la propia tabla de las entidades sin declarar un alias - o una columna particular (customerId en el ejemplo dado). Observa - además que puedes usar el elemento anidado de mapeo <formula> - si no te gusta usar el atributo. - - - - - - many-to-one - - - Una asociación ordinaria a otra clase persistente se declara usando - el elemento many-to-one. El modelo relacional es una - asociación muchos-a-uno: una clave foránea en una tabla está - referenciando la columna (o columnas) de la clave primaria de la tabla objetivo. - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - - - name: El nombre de la propiedad. - - - - - column (opcional): El nombre de la columna clave foránea. - También puede ser especificado por uno o varios elementos anidados - <column>. - - - - - class (opcional - por defecto al tipo de la propiedad - determinado por reflección): El nombre de la clase asociada. - - - - - cascade (opcional): Especifica qué operaciones deben - ir en cascada desde el objeto padre al objeto asociado - - - - - fetch (opcional - por defecto a 1select): - Escoge entre recuperación outer-join o por selección secuencial. - - - - - update, insert (opcional - por defecto a true) - especifica que las columnas mapeadas deben ser incluídas en las sentencias SQL - UPDATE y/o INSERT. Establecer ambas a - false permite una asociación puramente "derivada" cuyo - valor es inicializado desde alguna otra propiedad que mapea a las misma columna (o columnas), - o por un disparador, o por otra aplicación. - - - - - property-ref: (opcional) El nombre de la propiedad de la clase - asociada que está unida a la clave foránea. Si no se especifica, se usa - la clave primaria de la clase asociada. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - unique (opcional): Habilita la generación DDL de una - restricción de unicidad para la columna de clave foránea. Además, - permite que ésta sea el objetivo de una property-ref. - Esto hace efectivamente la multiplicidad de la asociación uno a uno. - - - - - not-null (opcional): Habilita la generación DDL de una - restricción de nulabilidad para las columnas de clave foránea. - - - - - optimistic-lock (opcional - por defecto a true): - Especifica que las actualizaciones a esta propiedad requieran o no la obtención - del bloqueo optimista. En otras palabras, determina si debe darse un incremento de versión - cuando esta propiedad esté desactualizada. - - - - - lazy (opcional - por defecto a proxy): - Por defecto, las asociaciones de punto único van con proxies. - lazy="true" especifica que esta propiedad debe ser - traída perezosamente cuando la variable de instancia sea accedida por primera - vez (requiere instrumentación del bytecode en tiempo de compilación). - lazy="false" especifica que la asociación siempre será - recuperada tempranamente. - - - - - not-found (opcional - por defecto a exception): - Especifica cómo deben manejarse las claves foráneas que referencien - filas inexistentes: ignore tratará una fila perdida como - una asociación nula. - - - - - entity-name (opcional): El nombre de entidad de la clase - asociada. - - - - - formula (opcional): una expresión SQL que define el valor - para una clave foránea computada. - - - - - - - - Establecer el valor del atributo cascade a cualquier valor - significativo distinto de none propagará ciertas - operaciones al objeto asociado. Los valores significativos son los nombres de las - operaciones básicas de Hibernate, persist, merge, delete, save-update, - evict, replicate, lock, refresh, así como los valores especiales - delete-orphan y all y combinaciones de operaciones - separadas por coma, por ejemplo, cascade="persist,merge,evict" o - cascade="all,delete-orphan". Para una explicación completa, - ver . - - - - Una declaración típica muchos-a-uno se parece a esto: - - - ]]> - - - El atributo property-ref debe ser usado solamente para el mapeo - de datos heredados donde una clave foránea referencia una clave única de - la tabla asociada, distinta de la clave primaria. Este es un modelo relacional feo. - Por ejemplo, supón que la clase Product tuviera un número - único serial que no es la clave primaria. (El atributo unique - controla la generación de DDL con la herramienta SchemaExport.) - - - ]]> - - - Entonces el mapeo para OrderItem debería usar: - - - ]]> - - - Sin embargo, esto no esta ciertamente alentado. - - - - Si la clave única referenciada abarca múltiples propiedades de la entidad asociada, - debes mapear las propiedades dentro de un elemento <properties>. - - - - - - one-to-one - - - Una asociación uno-a-uno a otra clase persistente se declara usando - un elemento one-to-one. - - - - - - - - - - - - - - - - ]]> - - - - name: El nombre de la propiedad. - - - - - class (opcional - por defecto al tipo de la propiedad - determinado por reflección): El nombre de la clase asociada. - - - - - cascade (opcional) especifica qué operaciones deben - ir en cascada desde el objeto padre al objeto asociado. - - - - - constrained (opcional) especifica que una restricción - de clave foránea de la tabla mapeada referencia a la tabla de la clase - asociada. Esta opción afecta el orden en que van en cascada - save() y delete(), y determina cuándo - la asociación pueden ser virtualizados por proxies (es también usado por - la herramienta de exportación de esquemas). - - - - - fetch (opcional - por defecto select): - Elige entre recuperación outer-join o recuperación por consulta secuencial. - - - - - property-ref: (opcional) El nombre de una propiedad de la clase - asociada que esté unida a la clave primaria de esta clase. Si no se especifica, - se usa la clave primaria de la clase asociada. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - formula (opcional): Casi todas las asociaciones uno-a-uno mapean - a la clave primaria de la entidad propietaria. En el raro caso en que este no sea el caso, - puedes especificar alguna otra columna, o columnas, o expresión para unir usando una - fórmula SQL. (Para un ejemplo ver org.hibernate.test.onetooneformula). - - - - - lazy (opcional - por defecto a proxy): - Por defecto, las asociaciones de punto único van con proxies. - lazy="true" especifica que esta propiedad debe ser - traída perezosamente cuando la variable de instancia sea accedida por primera - vez (requiere instrumentación del bytecode en tiempo de compilación). - lazy="false" especifica que la asociación siempre será - recuperada tempranamente. Observa que si constrained="false", - la aplicación de proxies es imposible e Hibernate traerá temprano la - asociación! - - - - - - - Hay dos variedades de asociaciones uno-a-uno: - - - - asociaciones de clave primaria - - - asociaciones de clave foráneas única - - - - - Las asociaciones de clave primaria no necesitan una columna de tabla extra; si dos filas - están relacionadas por la asociación entonces las dos filas de tablas comparten - el mismo valor de clave primaria. Por lo tanto, si quieres que dos objetos estén relacionados - por una asociación de clave primaria, debes asegurarte que se les asigne el mismo valor de - identificador! - - - - Para una asociación de clave primaria, añade los siguientes mapeos a - Employee y Person, respectivamente. - - - ]]> - ]]> - - - Ahora debemos asegurarnos que las claves primarias de las filas relacionadas en las tablas - PERSON y EMPLOYEE sean iguales. Usamos una estrategia especial de generación de identificador - de Hibernate llamada foreign: - - - - - - employee - - - ... - -]]> - - - A una instancia recién salvada de Person se le asigna entonces - el mismo valor de clave primaria con que la instancia Employee - referida por la propiedad employee de esta Person. - - - - Alternativamente, una clave foránea con una restricción de unicidad, desde - Employee a Person, puede ser expresada como: - - - ]]> - - - Y esta asociación puede hacerse bidireccional agregando lo siguiente al mapeo de - Person : - - - ]]> - - - - - natural-id - - - - - ...... -]]> - - - Aunque recomendamos el uso de claves delegadas como claves primarias, todavía debes - intentar identificar claves naturales para todas las entidades. Una clave natural es una - propiedad o combinación de propiedades que es única y no nula. Si además - es inmutable, mejor aún. Mapea las propiedades de la clave natural dentro del elemento - <natural-id>. Hibernate generará las restricciones de clave - única y nulabilidad necesarias, y tu mapeo será más auto-documentado. - - - - Recomendamos fuertemente que implementes equals() y - hashCode() para comparar las propiedades de clave natural - de la entidad. - - - - Este mapeo no está concebido para usar con entidades con claves - primarias naturales. - - - - - - mutable (opcional, por defecto a false): - Por defecto, se asume que las propiedades de identificadores naturales son - inmutables (constantes). - - - - - - - - - component, dynamic-component - - - El elemento <component> mapea propiedades de un objeto - hijo a columnas de la tabla de la clase padre. Los componentes pueden a su vez - declarar sus propias propiedades, componentes o colecciones. Ver debajo "Componentes". - - - - - - - - - - - - - - - - - - ........ -]]> - - - - name: El nombre de la propiedad. - - - - - class (opcional - por defecto al tipo de la propiedad - determinado por reflección): El nombre de la clase del componente (hijo). - - - - - insert: Aparecen las columnas mapeadas en - INSERTs SQL? - - - - - update: Aparecen las columnas mapeadas en - UPDATEs SQL? - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - lazy (opcional - por defecto a false): Especifica - que este componente debe ser recuperado perezosamente cuando la variable de instancia - sea accedida por primera vez (requiere instrumentación de bytecode en tiempo de - compilación). - - - - - optimistic-lock (opcional - por defecto a true): - Especifica si las actualizaciones de este componente requieren o no la - adquisición de un bloqueo optimista. En otras palabras, determina si - debe ocurrir un incremento de versión cuando esta propiedad está - desactualizada. - - - - - unique (opcional - por defecto a false): - Especifica que existe una restricción de unicidad sobre todas las - columnas mapeadas del componente. - - - - - - - Las etiquetas hijas <property> mapean propiedades de la - clase hija columnas de la tabla. - - - - El elemento <component> permite un subelemento - <parent> que mapea una propiedad de la clase del componente - como una referencia de regreso a la entidad contenedora. - - - - El elemento <dynamic-component> permite que un - Map sea mapeado como un componente, donde los nombres de - las propiedades se corresponden a las claves del mapa, ver . - - - - - - properties - - - El elemento <properties> permite la definición de - un grupo de propiedades lógico con nombre de una clase. El uso más - importante de la contrucción es que permite que una combinación - de propiedades sea objetivo de una property-ref. Es también - una forma conveniente de definir una restricción de unicidad multicolumna. - - - - - - - - - - - - - - - ........ -]]> - - - - name: El nombre lógico del agrupamiento - - no un nombre de propiedad real. - - - - - insert: Aparecen las columnas mapeadas en - INSERTs SQL? - - - - - update: Aparecen las columnas mapeadas en - UPDATEs SQL? - - - - - optimistic-lock (opcional - por defecto a true): - Especifica si las actualizaciones de estas propiedades requieren o no de la - adquisición de un bloqueo optimista. En otras palabras, determina si - debe ocurrir un incremento de versión cuando estas propiedades están - desactualizadas. - - - - - unique (opcional - por defecto a false): - Especifica que existe una restricción de unicidad sobre todas las - columnas mapeadas del componente. - - - - - - - Por ejemplo, si tenemos el siguiente mapeo de <properties>: - - - - - ... - - - - - -]]> - - - Entonces puede que tengamos alguna asociación de datos heredados que se refiera - a esta clave única de la tabla de Person, en vez de la clave - primaria: - - - - - - -]]> - - - No recomendamos el uso de este tipo de cosas fuera del contexto del mapeo de - datos heredados. - - - - - - subclass - - - Finalmente, la persistencia polimórfica requiere la declaración - de la clase persistente raíz. Para la estrategia de mapeo - tabla-por-jerarquía-de-clases, se usa la declaración de - <subclass>. - - - - - - - - - - - - - ..... -]]> - - - - name: El nombre de clase cualificado completamente - de la subclase. - - - - - discriminator-value (opcional - por defecto al nombre de la clase): - Un valor que distingue a subclases individuales. - - - - - proxy (opcional): Especifica una clase o interface a usar para - proxies de inicialización perezosa. - - - - - lazy (opcional, por defecto a true): - Establecer lazy="false" deshabilita el uso de recuperación - perezosa. - - - - - - - Cada subclase debe declarar sus propias propiedades persistentes y subclases. - Se asume que las propiedades <version> y <id> - son heredadas de la clase raíz. Cada subclase en una jerarquía debe - definir un discriminator-value único. Si no se especifica ninguno, - se usa el nombre completamente cualificado de clase Java. - - - - Es posible definir mapeos subclass, union-subclass, - y joined-subclass en documentos de mapeo separados, directamente debajo - de hibernate-mapping. Esto te permite extender una jerarquía de clases - con sólo agregar un nuevo fichero de mapeo. Debes especificar un atributo - extends en el mapeo de la subclase, mencionando una superclase previamente mapeada. - Nota: Previamente esta funcionalidad hacía importante el orden de los documentos de mapeo. - Desde Hibernate3, el orden de los ficheros de mapeo no importa cuando se usa la palabra reservada - extends. El orden dentro de un mismo fichero de mapeo todavía necesita ser definido como - superclases antes de subclases. - - - - - - -]]> - - - Para información acerca de mapeos de herencia, ver . - - - - - - joined-subclass - - - Alternativamente, cada subclase puede ser mapeada a su propia tabla - (estrategia de mapeo tabla-por-subclase). El estado heredado se recupera - uniendo con la tabla de la superclase. - Usamos el elemento <joined-subclass>. - - - - - - - - - - - - - - - ..... -]]> - - - - name: El nombre de clase completamente cualificado de - la subclase. - - - - - table: El nombre de tabla de la subclase. - - - - - proxy (opcional): Especifica una clase o interface a - usar para proxies de inicializacón perezosa. - - - - - lazy (opcional, por defecto a true): - Establecer lazy="false" deshabilita el uso de recuperación - perezosa. - - - - - - - No se requiere de una columna discriminadora para esta estrategia de mapeo. Cada subclase debe, - sin embargo, declarar una columna de tabla que tenga el identificador del objeto usando el - elemento <key>. El mapeo del comienzo del capítulo - debería ser reescrito como: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Para información acerca de mapeos de herencia, ver . - - - - - - union-subclass - - - Una tercera opción es mapear sólo las clases concretas de una - jerarquía de clases a tablas, (la estrategia tabla-por-clase-concreta) - donde cada tabla define todo el estado persistente de la clase, incluyendo el - estado heredado. En Hibernate, no es absolutamente necesario mapear dichas - jerarquías de herencia. Puedes simplemente mapear cada clase con una - declaración <class> separada. Sin embargo, - si deseas usar asociaciones polimórficas (por ejemplo, una asociación - a la superclase de tu jerarquía), debes usar el mapeo - <union-subclass>. - - - - - - - - - - - - - ..... -]]> - - - - name: El nombre de clase completamente cualificado de la subclase. - - - - - table: El nombre de tabla de la subclase. - - - - - proxy (optional): Especifica una clase o interface a - usar para proxies de inicializacón perezosa. - - - - - lazy (opcional, por defecto a true): - Establecer lazy="false" deshabilita el uso de recuperación - perezosa. - - - - - - - No se requiere columna o columna clave discriminadora para esta estrategia de mapeo. - - - - Para información acerca de mapeos de herencia, ver . - - - - - - join - - - Usando el elemento <join>, es posible mapear - propiedades de una clase a varias tablas. - - - - - - - - - - - - - - - - - ... -]]> - - - - - table: El nombre de la clase unida. - - - - - schema (opcional): Sobrescribe el nombre de esquema - especificado por el elemento raíz <hibernate-mapping>. - - - - - catalog (opcional): Sobrescribe el nombre de catálogo - especificado por el elemento raíz <hibernate-mapping>. - - - - - fetch (opcional - por defecto a join): - Si se establece a join, por defecto, Hibernate usará - una unión interior (inner join) para recuperar un <join> - definido por una clase o sus superclases y una unión externa (outer join) - para un <join> definido por una subclase. - Si se establece a select, entonces Hibernate usará una - select secuencial para un <join> definido en una subclase, - que será publicada sólo si una fila resulta representar una instancia - de la subclase. Las uniones interiores todavía serán usados para - recuperar un <join> definido por la clase y sus superclases. - - - - - inverse (opcional - por defecto a false): - De habilitarse, Hibernate no intentará insertar o actualizar las propiedades - definidas por esta unión. - - - - - optional (opcional - por defecto a false): - De habilitarse, Hibernate insertará una fila sólo si las propiedades - definidas por esta unión son no nulas y siempre usará una unión - externa para recuperar las propiedades. - - - - - - - Por ejemplo, la información domiciliaria de una persona puede ser mapeada - a una tabla separada (preservando a la vez la semántica de tipo de valor para - todas las propiedades): - - - - - ... - - - - - - - - ...]]> - - - Esta funcionalidad es a menudo solamente útil para modelos de datos - heredados; recomendamos menos tablas que clases un modelo de dominio más - granularizado. Sin embargo, es útil para cambiar entre estrategias de mapeo - de herencias en una misma jerarquía, como se explica luego. - - - - - - key - - - Hasta ahora hemos visto el elemento <key> pocas veces. - Aparece en cualquier sitio en que el elemento padre de mapeo defina una unión - a una nueva tabla, y define la clave foránea en la tabla unida, - que referencia la clave primaria de la tabla original. - - - - - - - - - - - - ]]> - - - - - column (opcional): El nombre de columna de la clave foránea. - Puede ser también especificado por elemento(s) anidado(s) - <column>. - - - - - on-delete (opcional, por defecto a noaction): - Especifica si la restricción de clave foránea tiene el borrado en cascada - habilitado a nivel de base de datos. - - - - - property-ref (opcional): Especifica que la clave foránea - referencia columnas que no son del la clave primaria de la tabla original. - (Provisto para datos heredados.) - - - - - not-null (opcional): Especifica que las columnas de la clave - foránea son no nulables (esto está implicado si la clave foránea - es también parte de la clave primaria). - - - - - update (opcional): Especifica que la clave foránea nunca - debe ser actualizada (esto está implicado si la clave foránea - es también parte de la clave primaria). - - - - - unique (opcional): Especifica que la clave foránea - debe tener una restricción de unicidad (esto está implicado si - la clave foránea es también la clave primaria). - - - - - - - Recomendamos que, para los sistemas en donde el rendimiento sea importante, todas las - claves deben ser definidas on-delete="cascade", e Hibernate usará - una restricción ON CASCADE DELETE a nivel de base de datos, - en vez de muchas sentencias DELETE individuales. Ten en cuenta que - esta funcionalidad se salta la habitual estrategia de bloqueo optimista de Hibernate para - datos versionados. - - - - Los atributos not-null y update son útiles - al mapear una asociación uno a muchos unidireccional. Si mapeas una uno a muchos - unidireccional a una clave foránea no nulable, debes declarar - la columna clave usando <key not-null="true">. - - - - - - los elementos column y formula - - Cualquier elemento de mapeo que acepte un atributo column aceptará - alternativamente un subelemento <column>. De forma similar, - <formula> es una alternativa al atributo formula. - - - ]]> - - expresión SQL]]> - - - Los atributos column y formula pueden - incluso ser combinados dentro del mismo mapeo de propiedad o asociación para - expresar, por ejemplo, condiciones de unión exóticas. - - - - - 'MAILING' -]]> - - - - - import - - - Supón que tu aplicación tiene dos clases persistentes con el mismo nombre, - y no quieres especificar el nombre completamenta cualificado (paquete) en las consultas - Hibernate. Las clases pueden ser "importadas" explícitamente, en vez de confiar en - auto-import="true". Puedes incluso importar clases e interfaces que - no estén mapeadas explícitamente. - - - ]]> - - - - - - - ]]> - - - - class: El nombre de clase completamente cualificado de - cualquier clase Java. - - - - - rename (opcional - por defecto al nombre de clase sin cualificar): - Un nombre que será usado en el leguaje de consulta. - - - - - - - - - any - - - Hay un tipo más de mapeo de propiedad. El elemento de mapeo <any> - define una asociacián polimórfica a clases desde múltiples tablas. Este tipo - de mapeo siempre requiere más de una columna. La primera columna contiene el tipo de la - entidad asociada. Las columnas restantes contienen el identificador. Es imposible especificar una - restricción de clave foránea para este tipo de asociación, por lo que - esto ciertamente no está concebido como la forma habitual de mapear asociaciones - (polimórficas). Sólo debes usar esto en casos muy especiales (por ejemplo, - trazas de auditoréa, datos de sesión de usuario, etc). - - - - El atributo meta-type permite a la aplicación especificar un tipo - personalizado que mapee columnas de base de datos a clases persistentes que tengan propiedades - identificadoras del tipo especificado por id-type. Debes especificar el - mapeo de valores del meta-type a nombres de clase. - - - - - - - - -]]> - - - - - - - - - - - - - - ..... - - - ..... -]]> - - - - name: el nombre de la propiedad. - - - - - id-type: el tipo del identificador. - - - - - meta-type (opcional - por defecto a string): - Cualquier tipo que sea permitido para un mapeo de discriminador. - - - - - cascade (opcional- por defecto a none): - el estilo de cascada. - - - - - access (opcional - por defecto a property): La - estrategia que Hibernate debe usar para acceder al valor de la propiedad. - - - - - optimistic-lock (opcional - por defecto a true): - Especifica si las actualizaciones de esta propiedad requieren o no de la - adquisición del bloqueo optimista. En otras palabras, determina si debe ocurrir - un incremento de versión cuando esta propiedad está desactualizada. - - - - - - - - - - - Tipos de Hibernate - - - Entidades y Valores - - - Para entender el comportamiento de varios objetos a nivel de lenguaje Java - con respecto al servicio de persistencia, necesitamos clasificarlos en dos grupos: - - - - Una entidad existe independientemente de cualquier otros - objetos que referencien a la entidad. Contrasta esto con el model habitual de Java - donde un objeto desreferenciado es recolectado como basura. Las entidades deben ser - salvadas y borradas explícitamente (excepto que las grabaciones y borrados - puedan ser tratados en cascada desde una entidad padre a sus hijos). - Esto es diferente al modelo de persistencia de objetos por alcance - y se corresponde - más de cerca a cómo los objetos de aplicación son usados - habitualmente en grandes sistemas. Las entidades soportan referencias circulares y - compartidas, que tambié pueden ser versionadas. - - - - El estado persistente de una entidad consiste en referencias a otras entidades - e instancias de tipo valor. Los valores son primitivos, - colecciones (no lo que está dentro de la colección), componentes - y ciertos objetos inmutables. A diferencia de las entidades, los valores - (en particular las colecciones y los componentes) son - hechos persitentes y borrados por alcance. Como los objetos valor (y primitivos) - son persistidos y borrados junto a sus entidades contenedoras, no pueden ser - versionados independientemente. Los valores no tienen identidad independiente, - por los que no pueden ser compartidos por dos entidades o colleciones. - - - - Hasta ahora, hemos estado usando el término "clase persistente" - para referirnos a entidades. Continuaremos haciéndolo. Hablando - estrictamente, sin embargo, no todas la clases con estado persistente - definidas por el usuario son entidades. Un componente - es una clase definida por el usuario con semántica de valor. - Una propiedad Java de tipo java.lang.String también - tiene semántica de valor. Dada esta definición, podemos decir - que todos los tipo (clases) provistos por el JDK tienen una semántica - de tipo valor en Java, mientras que los tipos definidos por el usuario - pueden ser mapeados con semántica de tipo valor o de entidad. - La desición corre por cuenta del desarrollador de la aplicación. - Un buen consejo para una clase entidad en un modelo de dominio son las referencias - compartidas a una sola instancia de esa clase, mientras que la composición - o agregación usualmente se traducen a un tipo de valor. - - - - Volveremos a visitar ambos conceptos a lo largo de la documentación. - - - - EL desafío es mapear el sistema de tipos de Java (y la definición - de entidades y tipos de valor de los desarrolladores) al sistema de tipos de - SQL/base de datos. EL puente entre ambos sistemas es provisto por Hibernate: - para las entidades usamos <class>, - <subclass>, etc. Para los tipos de valor usamos - <property>, <component>, etc, - usualmente con un atributo type. El valor de este atributo - es el nombre de un tipo de mapeo de Hibernate. Hibernate - provee de fábrica muchos mapeos (para tipos de valores del JDK - estándar). Puedes escribir tus propios mapeos de tipo, así como - implementar tus estrategias de conversión personalizadas, como veremos luego. - - - - Todos los tipos prefabricados de Hibernate soportan semántica de nulos - excepto las colecciones. - - - - - - Tipos de valores básicos - - - Los tipos de mapeo básicos prefabricados pueden ser - categorizado a grandes rasgos en: - - - - integer, long, short, float, double, character, byte, - boolean, yes_no, true_false - - - Mapeos de tipos primitivos de Java o clases de envoltura a - la tipos de columna SQL (especícifica del vendedor). - boolean, yes_no y true_false - son codificaciones alternativas a boolean de - Java o java.lang.Boolean. - - - - - string - - - Un mapeo del tipo java.lang.String a - VARCHAR (u Oracle VAARCHAR2). - - - - - date, time, timestamp - - - Mapeos de tipo desde java.util.Date y sus subclases - a tipos SQL DATE, TIME y - TIMESTAMP (o equivalente). - - - - - calendar, calendar_date - - - Mapeos de tipo desde java.util.Date y sus subclases - a tipos SQL TIMESTAMP y DATE - (o equivalente). - - - - - big_decimal, big_integer - - - Mapeos de tipo desde java.math.BigDecimal y - java.math.BigInteger a NUMERIC - (o NUMBER de Oracle). - - - - - locale, timezone, currency - - - Mapeos de tipo desde java.util.Locale, - java.util.TimeZone y - java.util.Currency a - VARCHAR (o VARCHAR2 de Oracle). - Las instancias de Locale y Currency - son mapeadas a sus códigos ISO. Las instancias de - TimeZone son mapeadas a sus ID. - - - - - class - - - Un mapeo de tipo java.lang.Class a - VARCHAR (o VARCHAR2 de Oracle). - Una Class es mapeara a su nombre completamente - cualificado. - - - - - binary - - - Mapea arreglos de bytes a un tipo binario SQL apropiado. - - - - - text - - - Mapea cadenas largas Java al tipo SQL CLOB o - TEXT. - - - - - serializable - - - Mapea tipos serializables Java a un tipo binario SQL apropiado. - Puedes además indicar el tipo serializable - de Hibernate con el nombre de una clase o interface serializable Java - que no sea por defecto un tipo básico. - - - - - clob, blob - - - Mapeos de tipo para las clases JDBC java.sql.Clob y - java.sql.Blob. Estos tipos pueden ser inconvenientes - para algunas aplicaciones, pues el objeto blob o clob no puede ser reusado - fuera de una transacción (Además, el soporte del driver suele - ser malo e inconsistente). - - - - - - - - - Los identificadores únicos de entidades y collecciones pueden ser de cualquier - tipo básico excepto binary, blob - y clob. - (Los identificadores compuestos están también permitidos, ver debajo.) - - - - Los tipos de valor básicos tienen sus constantes Type - correspondientes definidas en org.hibernate.Hibernate. Por ejemplo, - Hibernate.STRING representa el tipo string. - - - - - - Tipos de valor personalizados - - - Es relativamente fácil para los desarrolladores crear sus propios tipos de valor. - Por ejemplo, podrías querer persistir propiedades del tipo java.lang.BigInteger - a columnas VARCHAR. Hibernate no provee un tipo de fábrica para esto. - Pero los tipos personalizados no están limitados a mapear una propiedad (o elemento de colección) - a una sola columna de tabla. Así, por ejemplo, podrías tener una propiedad Java - getName()/setName() de tipo java.lang.String - que fuera persistida a las columnas FIRST_NAME, INITIAL, - SURNAME. - - - - Para implementar un tipo personalizado, implementa bien org.hibernate.UserType - o org.hibernate.CompositeUserType y declara las propiedades usando el nombre - de clase completamente cualificado del tipo. Revisa org.hibernate.test.DoubleStringType - para ver qué tipo de cosas son posibles. - - - - - -]]> - - - Observa el uso de etiquetas <column> para mapear una propiedad - a múltiples columnas. - - - - Las interfaces CompositeUserType, EnhancedUserType, - UserCollectionType, y UserVersionType proveen - soporte a usos más especializados. - - - - Puedes incluso proveer de parámetros a un UserType en el - fichero de mapeo. Para hacer esto, tu UserType debe implementar - la interface org.hibernate.usertype.ParameterizedType. Para - proveer de parámetros a tu tipo personalizado, puedes usar el elemento - <type> en tus ficheros de mapeo. - - - - - 0 - -]]> - - - Ahora el UserType puede recuperar el valor del parámetro - llamado default del objeto Properties - que se le pasa. - - - - Si usas cierto UserType muy frecuentemente, puede ser útil - definir un nombre corto para é. Puedes hacer esto usando el elemento - <typedef>. Los typedefs asignan un nombre a un tipo - personalizado, y pueden también contener una lista de valores por defecto - de parámetros si el tipo fuese parametrizado. - - - - 0 -]]> - - ]]> - - - también es posible sobrescribir los parámetros provistos en un typedef sobre - una base caso por caso usando parámetros de tipo en el mapeo de la propiedad. - - - - Aunque el rico espectro de tipos prefabricados y soporte de componentes de Hibernate - significa que raramente necesites usar un tipo personalizado; - sin embargo se considera una buena forma usar tipos personalizados para clases (no-entidades) - que aparezcan frecuentemente en tu aplicación. Por ejemplo, una clase - MonetaryAmount es una buena candidata para un - CompositeUserType, incluso cuando puede ser facilmente mapeada como un - componente. Un motivo para esto es la abstracción. Con un tipo personalizado, - tus documentos de mapeo estará impermeabilizados contra posibles cambios futuros en la - forma de representar valores monetarios. - - - - - - - - Mapeando una clase más de una vez - - Es posible proveer más de un mapeo para una clase persistente en particular. En este caso debes - especificar un nombre de entidad para desambiguar entr las instancias de las - dos entidades mapeadas. (Por defectom, el nombre de la entidad es el mismo que el nombre de la clase.) - Hibernate te deja especificar el nombre de entidad al trabajar con objetos persistentes, al escribir - consultas, o al mapear asociaciones a la entidad mencionada. - - - - ... - - - - - - - - ... - -]]> - - - Observa cómo las asociaciones ahora se especifican usando entity-name en vez de - class. - - - - - - - identificadores SQL encomillados - - Puedes forzar a Hibernate a encomillar un identificador en el SQL generado encerrando el nombre - de tabla o columna entre backticks en el documento de mapeo. Hibernate usará el estilo de - encomillado para el Dialect SQL (usualmente comillas dobles, excepto corchetes - para SQL Server y backsticks para MySQL). - - - - - - ... -]]> - - - - - - Alternativas de metadatos - - - XML no es para todos, asá que hay algunas formas alternativas de definir metadatos de mapeo O/R - en Hibernate. - - - - Usando marcado de XDoclet - - - Muchos usuarios de Hibernate prefieren embeber la información de mapeo directamente - en el código fuente usando las @hibernate.etiquetas XDoclet. - No cubriremos este enfoque en este documento, pues estrictamente es considerado parte - de XDoclet. Sin embargo, incluímos el siguiente ejemplo de la clase - Cat con mapeos XDoclet. - - - - - - Para más ejemplos de XDoclet e Hibernate ver en el sitio web de Hibernate. - - - - - - Usando anotaciones JDK 5.0 - - El JDK 5.0 introdujo anotaciones del estilo XDoclet a nivel del lenguaje, - con chequeo seguro de tipos en tiempo de compilación. Este mecanismo es más - potente y que las anotaciones XDoclet, y mejor soportado por herramientas e IDEs. - IntelliJ IDEA, por ejemplo, soporta auto-compleción y resaltado de sintaxis de anotaciones - JDK 5.0. La nueva revisión de la especificación de EJB (JSR-220) usa anotaciones - JDK 5.0 como el mecanismo primario de metadatos para beans de entidad. Hibernate3 implementa - el EntityManager del JSR-220 (la API de persistencia), y el soporte para - metadatos de mapeo está disponible vía el paquete Hibernate Annotations, - como una descarga por separado. Tanto metadatos de EJB3 (JSR-220) como de Hibernate3 están soportados. - - - - Este es un ejemplo de una clase POJO anotada como un bean de entidad EJB: - - - orders; - - // Getter/setter and business methods -}]]> - - - Ten en cuenta que el soporte a anotaciones JDK 5.0 (y JSR-220) es todavía un - trabajo en progreso y no completado. Por favor, para más detalles refiérete al modulo - de Anotaciones de Hibernate. - - - - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/batch.xml b/documentation/manual/es-ES/src/main/docbook/modules/batch.xml deleted file mode 100644 index b24fbf2ce7..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/batch.xml +++ /dev/null @@ -1,192 +0,0 @@ - - Procesamiento por lotes - - - Un enfoque ingenuo para insertar 100.000 filas en la base de datos usando Hibernate podría verse así: - - - - - - Esto podría caer sobre una OutOfMemoryException en algún sitio - cerca de la fila 50.000. Esto es porque Hibernate tiene en caché todas las instancias - de Customer recién instanciadas en el caché de nivel de sesión. - - - - En este capítulo te mostraremos cómo evitar este problema. Primero, sin embargo, - si estás haciendo procesamiento por lotes (batch processing), es absolutamente crítico - que habilites el uso de loteo JDBC, si pretendes lograr un rendimiento razonable. - Establece el tamaño de lote JDBC a un número razonable (digamos 10-50): - - - - - - Podrías además querer hacer este tipo de trabajo en un proceso donde la interacción con el caché de - segundo nivel esté completamente deshabilitado: - - - - - - Inserciones en lote - - - Al hacer persistentes objetos nuevos, debes limpiar con flush() y - llamar a clear() en la sesión regularmente, para controlar el tamaño - del caché de primer nivel. - - - - - - - - Actualizaciones en lote - - - Para recuperar y actualizar datos se aplican las mismas ideas. Adicionalmente, necesitas usar - scroll() para sacar ventaja de los cursores del lado del servidor en consultas - que devuelvan muchas filas de datos. - - - - - - - - update/delete en masa - - - Como ya se ha discutido, el mapeo objeto/relacional automático y transparente se refiere - al manejo de estado de objetos. Esto implica que el estado del objeto está disponible - en memoria, por lo tanto actualizar o borrar (usando UPDATE y - DELETE de SQL) datos directamente en la base de datos no afectará el - estado en memoria. Sin embargo, Hibernate provee métodos para la ejecución de sentencias - del estilo de UPDATE y DELETE de SQL que se realizan - a través del Lenguaje de Consulta de Hibernate (Hibernate Query Language o - HQL). - - - - La pseudo-sintáxis para sentencias UPDATE y DELETE es: - ( UPDATE | DELETE ) FROM? ClassName (WHERE WHERE_CONDITIONS)?. Algunos puntos - a tener en cuenta: - - - - - - En la cláusula-from, la palabra clave FROM es opcional - - - - - Puede haber sólo una clase mencionada en la cláusula-from, y no puede - tener un alias. - - - - - No puede especificarse ningún join (bien implícito o explícito) en una consulta masiva de HQL. - Pueden usarse subconsultas en la cláusula-where. - - - - - La cláusula-where es también opcional. - - - - - - Como un ejemplo, para ejecutar un UPDATE HQL, usa el - método Query.executeUpdate(): - - - - - - Para ejecutar un DELETE HQL, usa el mismo método Query.executeUpdate() - (el método está nombrado para aquellos familiarizados con - PreparedStatement.executeUpdate() de JDBC): - - - - - - El valor int devuelto por el método Query.executeUpdate() - indica el número de entidades afectadas por la operación. Considera que esto puede o no - correlacionarse al número de filas afectadas en la base de datos. Una operación masiva HQL podría - resultar en que se ejecuten múltiples sentencias de SQL reales, para joined-subclass, por ejemplo. - El número devuelto indica el número de entidades reales afectadas por la sentencia. Volviendo al - ejemplo de joined-subclass, un borrado contra una de las subclases puede resultar realmente en - borrados contra no sólo la tabla a la que está mapeada esa subclase, sino también la tabla "raíz" - y potencialmente tablas de joined-subclass más debajo en la jerarquía de herencia. - - - - Ten en cuenta que existen actualmente unas pocas limitaciones con las operaciones HQL masivas, - que serán atendidas en lanzamientos futuros; consulta la hoja de ruta de JIRA para más detalles. - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/best_practices.xml b/documentation/manual/es-ES/src/main/docbook/modules/best_practices.xml deleted file mode 100644 index 89bf4e2235..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/best_practices.xml +++ /dev/null @@ -1,229 +0,0 @@ - - Mejores Prácticas - - - - Escribe clase finamente granularizadas y mapealas usando <component>. - - - Usa una clase Dirección para encapsular calle, - distrito, estado, código postal. - Esto alienta la reutilización de código y simplifica el refactoring. - - - - - Declara las propiedades identificadoras en clases persistentes. - - - Hibernate hace opcionales las propiedades identificadoras. Existen todo tipo de razones - por las que debes usarlas. Recomendamos que los identificadores sean 'sintéticos' - (generados, sin ningún significado de negocio). - - - - - Identifica las claves naturales. - - - Identifica las claves naturales de todas las entidades, y mapealas usando - <natural-id>. Implementa equals() y - hashCode() para comparar las propiedades que componen la clave natural. - - - - - Coloca cada mapeo de clase en su propio fichero. - - - No uses un solo documento monolítico de mapeo. Mapea com.eg.Foo en - el fichero com/eg/Foo.hbm.xml. Esto tiene sentido particularmente en un - ambiente de equipo. - - - - - Carga los mapeos como recursos. - - - Despliega los mapeos junto a las clases que mapean. - - - - - Considera externalizar las cadenas de consulta. - - - Esta es una buena práctica si tus consultas llaman a funciones SQL que no son del - estándar ANSI. Externalizar las cadenas de consulta a ficheros de mapeo hará la - aplicación más portable. - - - - - Usa variables de ligado. - - - Igual que en JDBC, siempre remplaza valores no constantes con "?". ¡Nunca uses manipulación - de cadenas para ligar un valor no constante en una consulta! Incluso mejor, considera usar - parámetros con nombre en las consultas. - - - - - No manejes tus propias conexiones JDBC. - - - Hibernate deja a la aplicación administre las conexiones JDBC. Este enfoque debe considerarse - como último recurso. Si no puedes usar los provedores de conexión prefabricados, considera - prover tu propia implementación de org.hibernate.connection.ConnectionProvider. - - - - - Considera usar un tipo personalizado. - - - Supón que tienes un tipo Java, digamos de alguna biblioteca, que necesita hacerse persistente - pero no provee los métodos de acceso necesarios para mapearlo como un componente. Debes considerar - implementar org.hibernate.UserType. Este enfoque libera al código de aplicación - de implementar transformaciones a / desde un tipo Hibernate. - - - - - Usa JDBC codificado a mano en cuellos de botella. - - - En áreas del sistema de rendimiento crítico, algunos tipos de operaciones podrían beneficiarse - del JDBC directo. Pero por favor, espero hasta que sepas que algo es - un cuello de botella. Y no asumas que el JDBC directo es necesariamente más rápido. Si necesitas - usar JDBC directo, podría ser valioso abrir una Session de Hibernate y usar esa - conexión JDBC. De esta forma puedes usar aún la misma estrategia de transacción y el mismo - proveedor de conexiones subyacente. - - - - - Comprende la limpieza (flushing) de Session. - - - De vez en cuando la sesión sincroniza su estado persistente con la base de datos. El rendimiento - se verá afectado si este proceso ocurre demasiado frecuentemente. A veces puedes minimizar - limpieza innecesaria deshabilitando la limpieza automática o incluso cambiando el orden de las - consultas u otras operaciones en una transacción en particular. - - - - - En una aplicación en tres gradas, considera usar objetos separados. - - - Al usar una arquitectura de servlet / sesión, puedes pasar objetos persistentes en el bean de - sesión hacia y desde la capa de servlet / JSP. Usa una sesión nueva para atender el servicio de cada - petición. Usa Session.merge() o Session.saveOrUpdate() para - sincronizar los objetos con la base de datos. - - - - - En una arquitectura en dos gradas, considera usar contexto de persistencia largos. - - - Las transacciones de base de datos tienen que ser tan cortas como sea posible. Sin embargo, - frecuentemente es necesario implementar transacciones de aplicación - ejecutándose en largo, una sola unidad de trabajo desde el punto de vista de un usuario. - Una transacción de aplicación puede abarcar muchos ciclos petición/respuesta del cliente. - Es común usar objetos separados para implementar transacciones de aplicación. Una alternativa, - extremadamente apropiada en arquitecturas en dos gradas, es mantener un solo contacto de persistencia - abierto (sesión) para todo el ciclo de vida de la transacción de aplicación y simplemente - desconectar de la conexión JDBC al final de cada petición, y reconectar al comienzo de la - petición subsecuente. Nunca compartas una única sesión a través de más de una transacción - de aplicación, o estarás trabajando con datos añejos. - - - - - No trates la excepciones como recuperables. - - - Esto es más una práctica necesaria que una "mejor" práctica. Cuando ocurra una excepción, - deshaz (rollback) la Transaction y cierra la Session. - Si no lo haces, Hibernate no puede garantizar que el estado en memoria representa con exactitud - el estado persistente. Como un caso especial de esto, no uses Session.load() - para determinar si una instancia con el identificador dado existe en la base de datos. En cambio, - usa Session.get() o una consulta. - - - - - Prefiere la recuperación perezosa para las asociaciones. - - - Usa escasamente la recuperación temprana. Usa proxies y colecciones perezosas para la mayoría - de asociaciones a clases probablemente no estén mantenidas en el caché de segundo nivel. Para - las asociaciones a clases en caché, donde hay una probabilidad de acceso a caché extremadamente - alta, deshabilita explícitamente la recuperación temprana usando lazy="false". - Cuando sea apropiada la recuperación por unión (join fetching) para un caso de uso en particular, - usa una consulta con un left join fetch. - - - - - - Usa el patrón sesión abierta en vista, o una fase de ensamblado - disciplinada para evitar problemas con datos no recuperados. - - - - Hibernate liberal al desarrollador de escribir Objetos de Transferencia de Datos - (Data Transfer Objects) (DTO). En una arquitectura tradicional de EJB, los DTOs tienen - un propósito doble: primero, atacan el problema que los beans de entidad no son serializables. - Segundo, definen implícitamente una fase de ensamblado cuando se recuperan y se forman (marshalling) - todos los datos a usar por la vista en los DTOs antes de devolver el control a la grada de - presentación. Hibernate elimina el primer propósito. Sin embargo, aún necesitas una fase - de ensamblado (piensa en tus métodos de negocio como si tuviesen un contrato estricto con la grada - de presentación sobre qué datos están disponibles en los objetos separados) a menos que estés - preparado para tener el contexto de persistencia (la sesión) abierto a través del proceso - de renderización de la vista. ¡Esta no es una limitación de Hibernate! Es un requerimiento - fundamental de acceso seguro a datos transaccionales. - - - - - Considera abstraer tu lógica de negocio de Hibernate - - - Oculta el código de acceso a datos (Hibernate) detrás de una interface. Combina los patrones - DAO y Sesión de Hebra Local. Incluso puedes tener - algunas clases hechas persistentes por JDBC escrito a mano, asociadas a Hibernate por medio - de un UserType. (Este consejo está pensado para aplicaciones "suficientemente - grandes"; ¡no es apropiado para una aplicación con cinco tablas!) - - - - - No uses mapeos de asociación exóticos. - - - Son raros los casos de uso de asociaciones reales muchos-a-muchos. La mayor parte del tiempo - necesitas información adicional almacenada en una "tabla de enlace". En este caso, es mucho - mejor usar dos asociaciones uno-a-muchos a una clase de enlace intermedia. De hecho, pensamos - que la mayoría de asociaciones son uno-a-muchos y muchos-a-uno, debes ser cuidadoso al usr - cualquier otro estilo de asociación y preguntarte si es realmente necesario. - - - - - Prefiere las asociaciones bidireccionales. - - - Las asociaciones unidireccionales son más difíciles de consultar. En una aplicación grande, - casi todas las asociaciones deben ser navegables en ambas direcciones en consultas. - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/collection_mapping.xml b/documentation/manual/es-ES/src/main/docbook/modules/collection_mapping.xml deleted file mode 100644 index 21f28e6982..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/collection_mapping.xml +++ /dev/null @@ -1,1241 +0,0 @@ - - Mapeo de Colecciones - - - Colecciones persistentes - - - Hibernate requiere que los campos valuados en colección - persistentes sean declarados como un tipo de interface, por ejemplo: - - - - - - La interface real podría ser java.util.Set, - java.util.Collection, java.util.List, - java.util.Map, java.util.SortedSet, - java.util.SortedMap o ... lo que te guste! - (Donde "lo que te guste" significa que tendrás que escribir una - implementación de org.hibernate.usertype.UserCollectionType.) - - - - Nota cómo hemos inicializado la variable de instancia de - HashSet. Esta es la mejor forma de inicializar - propiedades valuadas en colección de instancias recién - instanciadas (no persistentes). Cuando haces persistente la instancia - - llamando a persist(), por ejemplo - Hibernate realmente - remplazará el HashSet con una instancia de una - implementación de Set propia de Hibernate. - Observa errores como este: - - - - - - Las colecciones persistentes inyectadas por Hibernate se comportan - como HashMap, HashSet, - TreeMap, TreeSet o - ArrayList, dependiendo del tipo de interface. - - - - Las instancias de colecciones tienen el comportamiento usual de tipos de valor. - Son automáticamente persistidas al ser referenciadas por un objeto - persistente y automáticamente borradas al desreferenciarse. Si una - colección es pasada de un objeto persistente a otro, sus elementos - serían movidos de una tabla a otra. Dos entidades pueden no - compartir una referencia a la misma instancia de colección. - Debido al modelo relacional subyacente, las propiedades valuadas en - colección no soportan la semántica de valor nulo. Hibernate no - distingue entre una referencia de colección nula y una colección - vacía. - - - - No debes tener que preocuparte demasiado por esto. Usa las colecciones - persistentes de la misma forma en que usas colecciones de Java ordinarias. - Sólo asegúrate que entiendes la semántica de las asociaciones - bidireccionales (discutida luego). - - - - - - Mapeos de colección - - - El elemento de mapeo de Hibernate usado para mapear una colección - depende del tipo de la interface. Por ejemplom un elemento - <set> se usa para mapear propiedades de tipo - Set. - - - - - - - - -]]> - - - Aparte de <set>, existen además - los elementos de mapeo <list>, - <map>, <bag>, - <array> y <primitive-array>. - El elemento <map> es representativo: - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - name el nombre de la propiedad de colección - - - - - table (opcional - por defecto al nombre de la propiedad) - el nombre de la tabla de coleciión (no usado para asociaciones - uno-a-muchos) - - - - - schema (opcional) el nombre de un esquema de tablas - para sobrescribir el esquema declarado en el elemento raíz - - - - - lazy (opcional - por defecto a true) - puede ser usado para deshabilitar la recuperación perezosa y - especificar que la asociación es siempre recuperada tempranamente - (no disponible para arrays) - - - - - inverse (opcional - por defecto a false) - marca esta colección como el extremo "inverso" de una asociación - bidireccional. - - - - - cascade (opcional - por defecto a none) - habilita operaciones en cascada a entidades hijas - - - - - sort (opcional) especifica una colección - con ordenamiento natural, o una clase comparadora - dada - - - - - order-by (opcional, sólo JDK1.4) especifica una columna - de tabla (o columnas) que definen el orden de iteración del - Map, Set o bag, junto a un - asc o desc opcional. - - - - - where (opcional) especifica una condición - WHERE de SQL arbitrario para ser usada al recuperar o - quitar la colección (útil si la colección debe - contener sólo un subconjunto de los datos disponibles) - - - - - fetch (opcional, por defecto a select) - Elige entre recuperación por unión externa (outer-join), - recuperar por selección secuencial, y recuperación por - subselección secuencial. - - - - - batch-size (opcional, por defecto a 1) - especifica un "tamaño de lote" para la recuperar - perezosamente instancias de esta colección. - - - - - access (opcional - por defecto a property): - La estrategia que debe usar Hibernate para acceder al valor de la - propiedad. - - - - - optimistic-lock (opcional - por defecto a true): - Especifica que los cambios de estado de la colección resultan en - incrementos de versión de la entidad dueña. (Para asociaciones - uno a muchos, frecuentemente es razonable deshabilitar esta opción.) - - - - - - - Claves foráneas de collección - - - Las instancias de colección se distinguen en la base de datos por la - clave foránea de la entidad que posee la colección. Se hace - referencia a esta clave foránea como la columna clave de - colección (o columnas) de la tabla de colección. - La columna clave de la colección es mapeada por el elemento - <key>. - - - - Puede haber una restricción de nulabilidad sobre la columna de clave - foránea. Para la mayoría de colecciones, esto está implicado. - Para asociaciones unidireccionales uno a muchos, la columna de clave - foránea es nulable por defecto, de modo que podrías necesitar - especificar not-null="true". - - - ]]> - - - La restricción de clave foránea puede usar - ON DELETE CASCADE. - - - ]]> - - - Mira el capítulo anterior por una definición completa del - elemento <key>. - - - - - - Elementos de collección - - - Las colecciones pueden contener casi cualquier tipo de Hibernate, incluyendo - todos los tipos básicos, componentes, y por supuesto, referencias a otras - entidades. Esta es una distinción importante: un objeto en una colección - puede ser manejado con una semántica de "valor" (su ciclo de vida depende - completamente del propietario de la colección) o podría ser una referencia - a otra entidad, con su propio ciclo de vida. En el último caso, sólo - el estado del "enlace" entre los dos objetos se considera mantenido por la - colección. - - - - Se hace referencia al tipo contenido como el tipo de elemento - de la colección. Los elementos de colección son - mapeados por <element> o - <composite-element>, o en el caso de referencias - de entidades, con <one-to-many> o - <many-to-many>. Las dos primeras mapean elementos - con semántica de valor, los dos siguientes son usados para mapear - asociaciones de entidades. - - - - - - Colecciones indexadas - - - Todos los mapeos de colección, excepto aquellos con semántica de - set o bag, necesitan una columna índice en la tabla - de colección, una columna que mapea a un índice de array, o - índice de List, o clave de Map. - El índice de un Map puede ser de cualquier tipo - básico, mapeado con <map-key>, o puede ser - una referencia de entidad, mapeada con <map-key-many-to-many>, - o puede ser un tipo compuesto, mapeado con <composite-map-key>. - El índice de un array o lista es siempre de tipo integer - y se mapea usando el elemento <list-index>. La columna - mapeada contiene enteros secuenciales (numerados desde cero, por defecto). - - - - - - - - ]]> - - - - column_name (requerido): El nombre de la columna que tiene - los valores índice de la colección. - - - - - base (opcional, por defecto a 0): El valor - de la columna índice que corresponde al primer elemento de la lista o - array. - - - - - - - - - - - - ]]> - - - - column (opcional): El nombre de la columna que tiene - los valores índice de la colección. - - - - - formula (opcional): Una fórmula SQL usada para - evaluar la clave del mapa. - - - - - type (requerido): el tipo de las claves del mapa. - - - - - - - - - - - - ]]> - - - - column (opcional): El nombre de la columna clave - foránea para los valores índice de la colección. - - - - - formula (opcional): Una fórmula SQL usada para - evaluar la clave foránea de la clave del mapa. - - - - - class (requerido): La clase de entidad usada como clave del mapa. - - - - - - - - Si tu tabla no tiene una columna índice, y deseas aún usar List como - tipo de propiedad, debes mapear la propiedad como un <bag> - de Hibernate. Un bag (bolsa) no retiene su orden al ser recuperado de la base de datos, - pero puede ser ordenado o clasificado opcionalmente. - - - - - - Hay absolutamente un rango de mapeos que pueden ser generados para colecciones, - cubriendo muchos modelos relacionales comunes. Te sugerimos que experimentes con - la herramienta de generación de esquemas para obtener una idea de cómo varias - declaraciones de mapeo se traducen a tablas de base de datos. - - - - Colecciones de valores y asociaciones muchos-a-muchos - - - Cualquier colección de valores o asociación muchos a muchos requiere una - tabla de colección dedicada con una columna o columnas - de clave foránea, columna de elemento de colección o - columnas y posiblemente una columna o columnas índice. - - - - Para una colección de valores, usamos la etiqueta <element>. - - - - - - - - - ]]> - - - - column (opcional): El nombre de la columna que tiene - los valores de los elementos de la colección. - - - - - formula (opcional): Una fórmula SQL usada para evaluar - el elemento. - - - - - type (requerido): El tipo del elemento de colección. - - - - - - - Una asociación muchos-a-muchos se especifica usando - el elemento <many-to-many>. - - - - - - - - - - - - - ]]> - - - - column (opcional): El nombre de la columna de clave - foránea del elemento. - - - - - formula (opcional): Una fórmula SQL opcional usada - para evaluar el valor de clave foránea del elemento. - - - - - class (requerido): El nombre de la clase asociada. - - - - - fetch (opcional - por defecto a join): - habilita la recuperación por unión externa o selección secuencial para esta - asociación. Este es un caso especial; para una recuperación completamente - temprana (en un solo SELECT) de una entidad y sus relaciones - muchos-a-muchos a otras entidades, deberías habilitar la recuperación - join no sólo de la colección misma, sino también con este - atributo en el elemento anidado <many-to-many>. - - - - - unique (opcional): Habilita la generación DDL de una - restricción de unicidad para la columna clave foránea. Esto hace la - multiplicidad de la asociación efectivamente uno a muchos. - - - - - not-found (opcional - por defecto a exception): - Especifica cómo serán manejadas las claves foráneas que referencian - filas perdidas: ignore tratará una fila perdida como - una asociación nula. - - - - - entity-name (opcional): El nombre de entidad de la clase - asociada, como una alternativa a class. - - - - - - - Algunos ejemplos, primero, un conjunto de cadenas: - - - - - -]]> - - - Un bag conteniendo enteros (con un orden de iteración determinado por el - atributo order-by): - - - - - -]]> - - - Un array de entidades - en este caso, una asociación muchos a muchos: - - - - - - -]]> - - - Un mapa de índices de cadenas a fechas: - - - - - - -]]> - - - Una lista de componentes (discutidos en el próximo capítulo): - - - - - - - - - - -]]> - - - - - Asociaciones uno-a-muchos - - - Una asociación uno a muchos enlaza las tablas de dos clases - por medio de una clave foránea, sin intervención de tabla de colección alguna. - Este mapeo pierde cierta semántica de colecciones Java normales: - - - - - - Una instancia de la clase entidad contenida no puede pertenecer - a más de una instancia de la colección. - - - - - Una instancia de la clase entidad contenida no puede aparecer en más - de un valor del índice de colección. - - - - - - Una asociación de Product a Part requiere la - existencia de una columna clave foránea y posiblemente una columna índice a la tabla - Part. Una etiqueta <one-to-many> indica - que ésta es una asociación uno a muchos. - - - - - - - - - ]]> - - - - class (requerido): El nombre de la clase asociada. - - - - - not-found (opcional - por defecto a exception): - Especifica cómo serán manejados los identificadores en caché que referencien - filas perdidas: ignore tratará una fila perdida como una - asociación nula. - - - - - entity-name (opcional): El nombre de entidad de la clase - asociada, como una alternativa a class. - - - - - - - Observa que el elemento <one-to-many> no necesita - declarar ninguna columna. Ni es necesario especificar el nombre de table - en ningún sitio. - - - - Nota muy importante: Si la columna clave foránea de una asociación - <one-to-many> es declarada NOT NULL, debes - declarar el mapeo de <key> not-null="true" - o usar una asociación bidireccional con el mapeo de colección - marcado inverse="true". Ver la discusión sobre asociaciones - bidireccionales más adelante en este capítulo. - - - - Este ejemplo muestra un mapa de entidades Part por nombre - (donde partName es una propiedad persistente de Part). - Observa el uso de un índice basado en fórmula. - - - - - - -]]> - - - - - - Mapeos de colección avanzados - - - Colecciones ordenadas - - - Hibernate soporta colecciones implementando java.util.SortedMap y - java.util.SortedSet. Debes especificar un comparador en el fichero de - mapeo: - - - - - - - - - - - -]]> - - - Los valores permitidos del atributo sort son unsorted, - natural y el nombre de una clase que implemente - java.util.Comparator. - - - - Las colecciones ordenadas realmente se comportan como java.util.TreeSet o - java.util.TreeMap. - - - - Si quieres que la misma base de datos ordene los elementos de colección usa el - atributo order-by de los mapeos set, - bag o map. Esta solución está disponible sólo - bajo el JDK 1.4 o superior (está implementado usando LinkedHashSet o - LinkedHashMap). Esto realiza la ordenación en la consulta SQL, - no en memoria. - - - - - - - - - - - -]]> - - - Observa que el valor del atributo order-by es una ordenación SQL, no - una ordenación HQL! - - - - Las asociaciones pueden incluso ser ordenadas por algún criterio arbitrario en tiempo de - ejecución usando un filter() de colección. - - - - - - - - Asociaciones bidireccionales - - - Una asociación bidireccional permite la nevegación desde - ambos "extremos" de la asociación. Son soportados dos tipos de asociación - bidireccional: - - - - uno-a-muchos - - - set o bag valorados en un extremo, monovaluados al otro - - - - - muchos-a-muchos - - - set o bag valorados a ambos extremos - - - - - - - - - Puedes especificar una asociación bidireccional muchos-a-muchos simplemente - mapeando dos asociaciones muchos-a-muchos a la misma tabla de base de datos - y declarando un extremo como inverse (cuál de ellos es tu - elección, pero no puede ser una colección indexada). - - - - He aquí un ejemplo de una asociación bidireccional muchos-a-muchos; cada categoría - puede tener muchos ítems y cada ítem puede estar en muchas categorías: - - - - - ... - - - - - - - - - ... - - - - - - -]]> - - - Los cambios hechos sólo al extremo inverso de la asociación no - son persistidos. Esto significa que Hibernate tiene dos representaciones en memoria - para cada asociación bidireccional, una enlaza de A a B y otra enlaza de B a A. - Esto es más fácil de entender si piensas en el modelo de objetos de Java y cómo - creamos una relación muchos-a-muchos en Java: - - - - - - El lado no-inverso se usa para salvar la representación en memoria a la base de datos. - - - - Puedes definir una asociación bidireccional uno-a-muchos mapeando una asociación uno-a-muchos - a la misma columna (o columnas) de tabla como una asociación muchos-a-uno y declarando el - extremo multivaluado inverse="true". - - - - - .... - - - - - - - - - .... - -]]> - - - Mapear un extremo de una asociación con inverse="true" no afecta - la operación de cascadas; éstos son conceptos ortogonales! - - - - - - Asociaciones bidireccionales con colecciones indexadas - - Requiere especial consideración una asociación bidireccional donde un extremo esté representado - como una <list> o <map>. Si hay una propiedad - de la clase hija que mapee a la columna índice, no hay problema, podemos seguir usando - inverse="true" en el mapeo de la colección: - - - - - .... - - - - - - - - - - .... - - -]]> - - - Pero, si no existe tal proiedad en la clase hija, no podemos pensar en la asociación como - verdaderamente bidireccional (hay información en un extremo de la asociación que no está - disponible en el otro extremo). En este caso, no podemos mapear la colección con - inverse="true". En cambio, podríamos usar el siguiente mapeo: - - - - - .... - - - - - - - - - - .... - -]]> - - - Nota que, en este mapeo, el extremo de la asociación valuado en colección es responsable de las - actualizaciones a la clave foránea. - - - - - - Asociaciones ternarias - - - Hay tres enfoques posibles para mapear una asociación ternaria. - Una es usar un Map con una asociación como su índice: - - - - - - -]]> - - - - - -]]> - - - Un segundo enfoque es simplemente remodelar la asociación como una clase de entidad. - Este es el enfoque que usamos más comunmente. - - - - Una alternativa final es usar elementos compuestos, que discutiremos más adelante. - - - - - - <literal>Usando un <idbag></literal> - - - Si has adoptado completamente nuestra visión de que las claves compuestas son una - cosa mala y que las entidades deben tener identificadores sitéticos (claves delegadas), - entonces podrías encontrar un poco raro que todas las asociaciones muchos a muchos y - las colecciones de valores que hemos mostrado hasta ahora mapeen a tablas con claves - compuestas! Ahora, este punto es discutible; una tabla de pura asociación no parece - beneficiarse demasiado de una clave delegada (aunque sí podría una - colección de valores compuestos). Sin embargo, Hibernate provee una funcionalidad que - te permite mapear asociaciones muchos a muchos y colecciones de valores a una tabla con - una clave delegada. - - - - El elemento <idbag> te permite mapear una List - (o Collection) con semántica de bag. - - - - - - - - -]]> - - - Como puedes ver, un <idbag> tiene un generador de id sintético, - igual que una clase de entidad! Una clave delegada diferente se asigna a cada fila - de la colección. Hibernate no provee ningún mecanismo para descubrir el valor de clave - delegada de una fila en particular, sin embargo. - - - - Observa que el rendimiento de actualización de un <idbag> es - mucho mejor que el de un <bag> regular! - Hibernate puede localizar filas individuales eficientemente y actualizarlas o borrarlas - individualmente, igual que si fuese una lista, mapa o conjunto. - - - - En la implementación actual, la estrategia de generación de identificador - native no está soportada para identificadores de colecciones - <idbag>. - - - - - - - - - - - - Ejemplos de colección - - - Las secciones previas son bastantes confusas. Así que miremos un ejemplo. - Esta clase: - - - - - - tiene una colección de instancias de Child. - Si cada hijo tiene como mucho un padre, el mapeo más natural es - una asociación uno-a-muchos: - - - - - - - - - - - - - - - - - - - - - -]]> - - - Esto mapea a las siguientes definiciones de tablas: - - - - - - Si el padre es requerido, usa una asociación bidireccional - uno-a-muchos: - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Observa la restricción NOT NULL: - - - - - - Alternativamente, si absolutamente insistes que esta asociación debe ser unidireccional, - puedes declarar la restricción NOT NULL en el mapeo de - <key>: - - - - - - - - - - - - - - - - - - - - - -]]> - - - En la otra mano, si un hijo pudiera tener múltiples padres, sería apropiada - una asociación muchos-a-muchos: - - - - - - - - - - - - - - - - - - - - - -]]> - - - Definiciones de tabla: - - - - - - Para más ejemplos y un paseo completo a través del mapeo de relaciones padre/hijo, - ver . - - - - Son posibles mapeos de asociación aún más complejos. Catalogaremos todas las posibilidades - en el próximo capítulo. - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/component_mapping.xml b/documentation/manual/es-ES/src/main/docbook/modules/component_mapping.xml deleted file mode 100644 index b62f726885..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/component_mapping.xml +++ /dev/null @@ -1,403 +0,0 @@ - - Mapeo de Componentes - - - La noción de un componente es reusada en muchos contextos diferentes, - para propósitos diferentes, a través de Hibernate. - - - - Objetos dependientes - - - Un componente es un objeto contenido que es persistido como un tipo de valor, no una - referencia de entidad. El término "componente" hace referencia a la noción orientada a - objetos de composición (no a componentes a nivel de arquitectura). Por ejemplo, podrías - modelar una persona como: - - - - - - - - Ahora Name puede ser persistido como un componente de - Person. Observa que Name define métodos - getter y setter para sus propiedades persistentes, pero no necesita declarar - ninguna interface ni propiedades identificadoras. - - - - Nuestro mapeo de Hibernate se vería así: - - - - - - - - - - - - -]]> - - - La tabla person tendría las columnas pid, - birthday, - initial, - first y - last. - - - - Como todos los tipos de valor, los componentes no soportan referencias compartidas. - En otras palabras, dos personas pueden tener el mismo nombre, pero los dos objetos - persona contendrían dos objetos nombre independientes, sólo "iguales" en valor. - La semántica de valor nulo de un componente es ad hoc. - Cuando se recargue el objeto contenedor, Hibernate asumirá que si todas las columnas del - componente son nulas, el componente entero es nulo. Esto debe estar bien para la mayoría - de propósitos. - - - - Las propiedades de un componentes pueden ser de cualquier tipo de Hibernate - (colecciones, muchos-a-uno, asociaciones, otros componentes, etc). Los componentes - anidados no deben ser considerados un uso exótico. Hibernate está - concebido para soportar un modelo de objetos granularizado en fino. - - - - El elemento <component> permite un subelemento - <parent> que mapee una propiedad de la clase del componente - como una referencia de regreso a la entidad contenedora. - - - - - - - - - - - - - -]]> - - - - - Colecciones de objetos dependientes - - - Las colecciones de componentes están soportadas (por ejemplo, - un array de tipo Name). Declara tu colección - de componentes remplazando la etiqueta <element> - por una etiqueta <composite-element>. - - - - - - - - - -]]> - - - Nota: si defines un Set de elementos compuestos, es muy - importante implementar equals() y hashCode() - correctamente. - - - - Los elementos compuestos pueden contener componentes pero no colecciones. - Si tu elemento compuesto contiene a su vez componentes, usa la etiqueta - <nested-composite-element>. Este es un caso bastante - exótico - una colección de componentes que a su vez tienen componentes. A esta - altura debes estar preguntándote si una asociación uno-a-muchos es más - apropiada. Intenta remodelar el elemento compuesto como una entidad - pero - observa que aunque el modelo Java es el mismo, el modelo relacional y la - semántica de persistencia siguen siendo ligeramente diferentes. - - - - Por favor observa que un mapeo de elemento compuesto no soporta - propiedades nulables si estás usando un <set>. - Hibernate tiene que usar cada columna para identificar un registro - al borrar objetos (no hay una columna clave primaria separada en la tabla del - elemento compuesto), lo que es imposible con valores nulos. Tienes que, o bien usar - sólo propiedades no nulas en un elemento compuesto o elegir un - <list>, <map>, - <bag> o <idbag>. - - - - Un caso especial de un elemento compuesto es un elemento compuesto con un - elemento anidado <many-to-one>. Un mapeo como este - te permite mapear columnas extra de una tabla de asociación muchos-a-muchos - a la clase del elemento compuesto. La siguiente es una asociación muchos-a-muchos - de Order a Item donde - purchaseDate, price y - quantity son propiedades de la asociación: - - - - .... - - - - - - - - - -]]> - - - Por supuesto, no puede haber una referencia a la compra del otro lado para la - navegación bidireccional de la asociación. Recuerda que los componentes son tipos de - valor no permiten referencias compartidas. Una sola Purchase puede - estar en el conjunto de una Order, pero no puede ser referenciada - por el Item al mismo tiempo. - - - Incluso son posibles las asociaciones ternarias (o cuaternarias, etc): - - - .... - - - - - - - -]]> - - - Los elementos compuestos pueden aparecer en consultas usando la misma - sintáxis que las asociaciones a otras entidades. - - - - - - Componentes como índices de Map - - - El elemento <composite-map-key> te permite mapear - una clase componente como la clave de un Map. Asegúrate que - sobrescribes hashCode() y equals() - correctamente en la clase componente. - - - - - Componentes como identificadores compuestos - - - Puedes usar un componente como un identidicador de una clase entidad. Tu clase - componente debe satisfacer ciertos requerimientos: - - - - - - Debe implementar java.io.Serializable. - - - - - Debe re-implementar equals() y - hashCode(), consistentemente con la - noción de base de datos de igualdad de clave compuesta. - - - - - - Nota: en Hibernat3, el segundo requerimiento no es absolutamente un - requerimiento rígido de Hibernate. Pero de todas formas, házlo. - - - - No puedes usar un IdentifierGenerator para generar claves - compuestas. La aplicación debe, en cambio, asignar sus propios identificadores. - - - - Usa la etiqueta <composite-id> (con elementos - anidados <key-property>) en lugar de la usual - declaración <id>. Por ejemplo, la clase - OrderLine tiene una clave primaria que depende de - la clave primaria (compuesta) de Order. - - - - - - - - - - - - - - - - - .... - -]]> - - - Ahora, cualquier clave foránea que referencie la tabla de OrderLine - es también compuesta. Debes declarar esto en tus mapeos de otras clases. Una asociación - a OrderLine sería mapeado así: - - - - - - - -]]> - - - (Nota que la etiqueta <column> es una alternativa al - atributo column en cualquier sitio.) - - - - Una asociación muchos-a-muchos a OrderLine - también usa la clave foránea compuesta: - - - - - - - - - -]]> - - - La colección de OrderLines en Order usaría: - - - - - - - - -]]> - - - (El elemento <one-to-many>, como es usual, no declara columnas.) - - - - Si OrderLine posee una colección por sí misma, tiene también - una clave foránea compuesta. - - - - .... - .... - - - - - - - - - ... - - -]]> - - - - - Componentes dinámicos - - - Puedes incluso mapear una propiedad de tipo Map: - - - - - - -]]> - - - La semántica de un mapeo <dynamic-component> es ídentica - a la de <component>. La ventaja de este tipo de mapeos es - la habilidad para determinar las propiedades reales del bean en tiempo de despliegue, - sólo con editar el documento de mapeo. La manipulación del documento de mapeo en tiempo - de ejecución es también posible, usando un analizador DOM. Incluso mejor, puedes acceder - (y cambiar) el metamodelo de tiempo de configuración de Hibernate por medio del objeto - Configuration. - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/configuration.xml b/documentation/manual/es-ES/src/main/docbook/modules/configuration.xml deleted file mode 100644 index 3ae6d99d12..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/configuration.xml +++ /dev/null @@ -1,1761 +0,0 @@ - - - Configuración - - - Debido a que Hibernate está diseñado para operar en muchos entornos - diferentes, hay un gran número de parámetros de configuración. - Afortunadamente, la mayoría tiene valores por defecto sensibles e Hibernate - se distribuye con un fichero hibernate.properties de ejemplo en - etc/ que muestra las diversas opciones. Tan sólo pon el - fichero de ejemplo en tu classpath y personalízalo. - - - - Configuración programática - - - Una instancia de org.hibernate.cfg.Configuration - representa un conjunto entero de mapeos de los tipos Java de una aplicación - a una base de datos SQL. La Configuration es usada para - construir una SessionFactory (inmutable). Los mapeos se - compilan de varios ficheros de mapeo XML. - - - - Puedes obtener una instancia de Configuration instanciándola - directamente y especificando documentos de mapeo XML. Si los ficheros de mapeo - están en el classpath, usa addResource(): - - - - - - Una forma alternativa (a veces mejor) es especificar la clase mapeada, - y dejar que Hibernate encuentre el documento de mapeo por ti: - - - - - - Entonces Hibernate buscará ficheros de mapeo llamados - /org/hibernate/auction/Item.hbm.xml y - /org/hibernate/auction/Bid.hbm.xml en el classpath. - Este enfoque elimina cualquier nombre de fichero en el código. - - - - Una Configuration también te permite especificar - propiedades de configuración: - - - - - - Esta no es la única forma de pasar propiedades de configuración - a Hibernate. La diversas opciones incluyen: - - - - - - Pasar una instancia de java.util.Properties a - Configuration.setProperties(). - - - - - Colocar hibernate.properties en un directorio - raíz del classpath. - - - - - Establecer propiedades System - usando java -Dproperty=value. - - - - - Incluir elementos <property> - en hibernate.cfg.xml (discutido luego). - - - - - - hibernate.properties es el enfoque más fácil - si quieres comenzar rápido. - - - - La Configuration está concebida como un objeto - de tiempo de arranque, para ser descartado una vez que una - SessionFactory es creada. - - - - - - Obteniendo una SessionFactory - - - Cuando todos los mapeos han sido parseados por la Configuration, - la aplicación debe obtener una fábrica de instancias de Session. - Esta fábrica está concebida para ser compartida por todas las hebras de - aplicación: - - - - - - Hibernate permite que tu aplicación instancie más de una - SessionFactory. Esto es útil si estás usando - más de una base de datos. - - - - - - Conexiones JDBC - - - Usualmente, quieres que la SessionFactory cree y almacene - en pool conexiones JDBC para ti. Si adoptas este enfoque, abrir una Session - es tan simple como: - - - - - - En cuanto hagas algo que requiera acceso a la base de datos, se obtendrá una - conexión JDBC del pool. - - - - Para que esto funcione, necesitamos pasar algunas propiedades de conexión - JDBC a Hibernate. Todos los nombres de propiedades y su semántica - están definidas en la clase org.hibernate.cfg.Environment. - Describiremos ahora las configuraciones más importantes para la conexión - JDBC. - - - - Hibernate obtendrá (y tendrá en pool) conexiones usando - java.sql.DriverManager si configuras las siguientes propiedades: - - - - Propiedades JDBC de Hibernate - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.connection.driver_class - - - clase del driver jdbc - - - - - hibernate.connection.url - - - URL de jdbc - - - - - hibernate.connection.username - - - usuario de base de datos - - - - - hibernate.connection.password - - - contraseña del usuario de base de datos - - - - - hibernate.connection.pool_size - - - número máximo de conexiones manejadas por pooling - - - - -
- - - El algoritmo de pooling de conexiones propio de Hibernate es sin embargo - algo rudimentario. Está concebido para ayudarte a comenzar y - no está concebido para usar en un sistema de producción - ni siquiera para pruebas de rendimiento. Debes usar un pool de terceros para - un mejor rendimiento y estabilidad. Sólo remplaza la propiedad - hibernate.connection.pool_size con configuraciones - específicas del pool de conexiones. Esto desactivará el pool - interno de Hibernate. Por ejemplo, podrías querer usar C3P0. - - - - C3P0 es un pool de conexiones JDBC de código abierto distribuido - junto a Hibernate en el directorio lib. - Hibernate usará su C3P0ConnectionProvider - para pooling de conexiones si estableces propiedades hibernate.c3p0.*. - Si quieres usar Proxool refiérete al hibernate.properties - empaquetado y al sitio web de Hibernate para más información. - - - - Aquí hay un fichero hibernate.properties de ejemplo para C3P0: - - - - - - Para su uso en un servidor de aplicaciones, casi siempre debes configurar - Hibernate para que obtenga conexiones de un Datasource - del servidor de aplicaciones registrado en JNDI. Necesitarás establecer - al menos una de las siguientes propiedades: - - - - Propiedades de Datasource de Hibernate - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.connection.datasource - - - nombre del datasource JNDI - - - - - hibernate.jndi.url - - - URL del provedor JNDI (optional) - - - - - hibernate.jndi.class - - - clase de la InitialContextFactory de JNDI (opcional) - - - - - hibernate.connection.username - - - usuario de base de datos (opcional) - - - - - hibernate.connection.password - - - contraseña del usuario de base de datos (opcional) - - - - -
- - - He aquí un fichero hibernate.properties de ejemplo - para un un datasource JNDI provisto por un servidor de aplicaciones. - - - - - - Las conexiones JDBC obtenidas de un datasource JNDI participarán automáticamente - en las transacciones del servidor de aplicaciones manejadas por contenedor. - - - - Pueden darse propiedades de conexión arbitrarias anteponiendo - "hibernate.connnection" al nombre de propiedad. - Por ejemplo, puedes especificar un charSet usando - hibernate.connection.charSet. - - - - Puedes definir tu propia estrategia de plugin para obtener conexiones JDBC implementando - la interface org.hibernate.connection.ConnectionProvider. Puedes - seleccionar una implementación personalizada estableciendo - hibernate.connection.provider_class. - - -
- - - Parámetros de configuración opcionales - - - Hay un número de otras propiedades que controlan el comportamiento - de Hibernate en tiempo de ejecución. Todas son opcionales y tienen - valores por defecto razonables. - - - - Advertencia: algunas de estas propiedades son de "nivel-de-sistema" - solamente.. Las propiedades a nivel de sistema sólo pueden ser - establecidas por medio de java -Dproperty=value o - hibernate.properties. No pueden - establecerse por medio de las otras técnicas arriba descritas. - - - - Propiedades de Configuración de Hibernate - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.dialect - - - El nombre de clase de un Dialect - de Hibernate que permite a Hibernate generar SQL optimizado - para una base de datos relacional en particular. - - ej. - full.classname.of.Dialect - - - - - - hibernate.show_sql - - - Escribe todas las sentencias SQL a la consola. - - ej. - true | false - - - - - - hibernate.default_schema - - - Cualifica, en el SQL generado, los nombres de tabla sin cualificar - con el esquema/tablespace dado. - - ej. - SCHEMA_NAME - - - - - - hibernate.default_catalog - - - Cualifica, en el SQL generado, los nombres de tabla sin cualificar - con el catálogo dado. - - ej. - CATALOG_NAME - - - - - - hibernate.session_factory_name - - - La SessionFactory será - ligada a este nombre en JNDI automáticamente - después de ser creada. - - ej. - jndi/composite/name - - - - - - hibernate.max_fetch_depth - - - Establece una "profundidad" máxima del - árbol de recuperación por outer join - para asociaciones de un extremo solo (uno-a-uno, muchos-a-uno). - Un 0 deshabilita la recuperación - por outer join por defecto. - - ej. - valores recomendados entre 0 y - 3 - - - - - - hibernate.default_batch_fetch_size - - - Establece un tamaño por defecto para la recuperación - en lote de asociaciones de Hibernate. - - ej. - valores recomendados 4, 8, - 16 - - - - - - hibernate.default_entity_mode - - - Establece un modo por defecto de representación de - entidades para todas las sesiones abiertas por esta - SessionFactory - - dynamic-map, dom4j, - pojo - - - - - - hibernate.order_updates - - - Fuerza a Hibernate a ordenar las actualizaciones SQL - por el valor de la clave primaria de los items a actualizar. - Esto resultará en menos bloqueos muertos de transacción - en sistemas altamente concurrentes. - - ej. - true | false - - - - - - hibernate.generate_statistics - - - De habilitarse, Hibernate colectará estadísticas - útiles para la afinación de rendimiento. - - ej. - true | false - - - - - - hibernate.use_identifer_rollback - - - De habilitarse, las propiedades identificadoras - generadas serán reseteadas a valores por - defecto cuando los objetos sean borrados. - - ej. - true | false - - - - - - hibernate.use_sql_comments - - - De activarse, Hibernate generará comentarios dentro del SQL, - para una más fácil depuración, por defecto a - false. - - ej. - true | false - - - - - -
- - - Propiedades de JDBC y Conexiones de Hibernate - - - - - - Nombre de propiedad - Propoósito - - - - - - hibernate.jdbc.fetch_size - - - Un valor distinto de cero que determina el tamaño - de recuperación de JDBC (llama a - Statement.setFetchSize()). - - - - - hibernate.jdbc.batch_size - - - Un valor distinto de cero habilita el uso de actualizaciones - en lote de JDBC2 por Hibernate. - - ej. - valores recomendados entre 5 y 30 - - - - - - hibernate.jdbc.batch_versioned_data - - - Establece esta propiedad a true si tu driver JDBC - devuelve cuentas correctas de filas desde executeBatch() - (usualmente es seguro activar esta opción). Hibernate usará - DML en lote para versionar automáticamente los datos. - Por defecto a false. - - ej. - true | false - - - - - - hibernate.jdbc.factory_class - - - Selecciona un Batcher personalizado. - La mayoría de las aplicaciones no necesitarán - esta propiedad de configuración. - - ej. - classname.of.BatcherFactory - - - - - - hibernate.jdbc.use_scrollable_resultset - - - Habilita el uso de resultados scrollables de JDBC2 por Hibernate. - Esta propiedad sólo es necesaria cuando se usan conexiones - JDBC provistas por el usuario, en caso contrario Hibernate usa los - metadatos de conexión. - - ej. - true | false - - - - - - hibernate.jdbc.use_streams_for_binary - - - Usa flujos (streams) al escribir/leer tipos - binary o serializable - a/desde JDBC (propiedad a nivel de sistema). - - ej. - true | false - - - - - - hibernate.jdbc.use_get_generated_keys - - - Habilita el uso de PreparedStatement.getGeneratedKeys() - de JDBC3 para traer claves generadas nativamente después de insertar. - Requiere un driver JDBC3+ y un JRE1.4+. Establécela a false si tu - driver tiene problemas con los generadores de identificador de Hibernate. - Por defecto, se intenta determinar las capacidades del driver usando los - metadatos de conexión. - - ej. - true|false - - - - - - hibernate.connection.provider_class - - - EL nombre de clase de un ConnectionProvider personalizado - que provea conexiones JDBC a Hibernate. - - ej. - classname.of.ConnectionProvider - - - - - - hibernate.connection.isolation - - - Establece el nivel de aislamiento de transacción JDBC. - Comprueba java.sql.Connection para valores - significativos pero observa que la mayoría de las bases de - datos no soportan todos los niveles de aislamiento. - - eg. - 1, 2, 4, 8 - - - - - - hibernate.connection.autocommit - - - Habilita compromiso automático (autocommit) para - las conexiones JDBC en pool (no recomendado). - - ej. - true | false - - - - - - hibernate.connection.release_mode - - - Especifica cuándo Hibernate debe liberar las conexiones JDBC. - Por defecto, una conexión JDBC es retenida hasta que la sesión - es cerrada explícitamente o desconectada. Para un datasource JTA - del servidor de aplicaciones, debes usar after_statement - para liberar agresivamente las conexiones después de cada llamada - JDBC. Para una conexión no JTA, frecuentemente tiene sentido liberar - la conexión al final de cada transacción, usando - after_transaction. auto eligirá - after_statement para las estrategias JTA o CMT - de transacción y after_transaction para la - estrategia JDBC de transacción. - - ej. - on_close (por defecto)| after_transaction | - after_statement | auto - - - - - - hibernate.connection.<propertyName> - - - Pasa la propiedad JDBC propertyName - a DriverManager.getConnection(). - - - - - hibernate.jndi.<propertyName> - - - Pasa la propiedad propertyName - a InitialContextFactory de JNDI. - - - - -
- - - Propiedades de Caché de Hibernate - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.cache.provider_class - - - El nombre de clase de un CacheProvider personalizado. - - ej. - classname.of.CacheProvider - - - - - - hibernate.cache.use_minimal_puts - - - Optimiza la operación del caché de segundo nivel - para minimizar escrituras, al costo de lecturas más frecuentes. - Esto es más útil para cachés en cluster y, - en Hibernate3, está habilitado por defecto para implementaciones - de caché en cluster. - - ej. - true|false - - - - - - hibernate.cache.use_query_cache - - - Habilita el caché de lectura, consultas individuales todavía - tienen que ponerse cachables. - - ej. - true|false - - - - - - hibernate.cache.use_second_level_cache - - - Puede ser usado para deshabilitar completamente el caché - de segundo nivel, que está habilitado por defecto para clases - que especifican un mapeo <cache>. - - ej. - true|false - - - - - - hibernate.cache.query_cache_factory - - - El nombre de clase de una interface QueryCache - personalizada, por defecto al StandardQueryCache - prefabricado. - - ej. - classname.of.QueryCache - - - - - - hibernate.cache.region_prefix - - - Un prefijo a usar para los nombres de región - del caché de segundo nivel. - - ej. - prefix - - - - - - hibernate.cache.use_structured_entries - - - Fuerza a Hibernate a almacenar los datos en el caché - de segundo nivel en un formato más amigable al humano. - - ej. - true|false - - - - - -
- - - Propiedades de Transacción de Hibernate - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.transaction.factory_class - - - El nombre de clase de un TransactionFactory - a usar con la API de Transaction de Hibernate - (por defectoa JDBCTransactionFactory). - - ej. - classname.of.TransactionFactory - - - - - - jta.UserTransaction - - - Un nombre JNDI usado por JTATransactionFactory para - obtener la UserTransaction JTA del servidor - de aplicaciones. - - ej. - jndi/composite/name - - - - - - hibernate.transaction.manager_lookup_class - - - El nombre de clase de un TransactionManagerLookup - requerido cuando el chaché a nivel de JVM está - habilitado o cuando se usa un generador alto/bajo en un - entorno JTA. - - ej. - classname.of.TransactionManagerLookup - - - - - - hibernate.transaction.flush_before_completion - - - De habilitarse, la sesión se limpiará (flushed) - automáticamente durante la fase previa a la compleción - de la transacción. (Muy útil cuando se usa Hibernate - con CMT). - - ej. - true | false - - - - - - hibernate.transaction.auto_close_session - - - De habilitarse, la sesión será cerrada automáticamente - durante la fase posterior a la compleción de la transacción. - (Muy útil cuando se usa Hibernate con CMT). - - ej. - true | false - - - - - -
- - - Propiedades Misceláneas - - - - - - Nombre de propiedad - Propósito - - - - - - hibernate.query.factory_class - - - Elige la implementación de parser HQL. - - ej. - org.hibernate.hql.ast.ASTQueryTranslatorFactory or - org.hibernate.hql.classic.ClassicQueryTranslatorFactory - - - - - - hibernate.query.substitutions - - - Mapeos de símbolos en consultas Hibernate a - símbolos SQL. (los símbolos puedem ser - nombres de función o literales, por ejemplo). - - ej. - hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC - - - - - - hibernate.hbm2ddl.auto - - - Exporta automáticamente DDL de esquema cuando - al crear la SessionFactory. - Con create-drop, el esquema de - base de datos será desechado cuando la - SessionFactory se cierre explícitamente. - - ej. - update | create | create-drop - - - - - - hibernate.cglib.use_reflection_optimizer - - - Habilita el uso de CGLIB en vez de refleccón en tiempo de - ejecución (propiedad a nivel de sistema). La reflección - a veces puede ser útil ante la aparición de problemas. - Observa que Hibernate siempre requiere CGLIB incluso si desactivas - el optimizador. No puedes establecer esta propiedad en - hibernate.cfg.xml. - - ej. - true | false - - - - - -
- - - SQL Dialects - - - You should always set the hibernate.dialect property to the correct - org.hibernate.dialect.Dialect subclass for your database. If you - specify a dialect, Hibernate will use sensible defaults for some of the - other properties listed above, saving you the effort of specifying them manually. - - - - Dialectos SQL de Hibernate(<literal>hibernate.dialect</literal>) - - - - - - RDBMS - Dialecto - - - - - DB2 org.hibernate.dialect.DB2Dialect - - - DB2 AS/400 org.hibernate.dialect.DB2400Dialect - - - DB2 OS390 org.hibernate.dialect.DB2390Dialect - - - PostgreSQL org.hibernate.dialect.PostgreSQLDialect - - - MySQL org.hibernate.dialect.MySQLDialect - - - MySQL con InnoDB org.hibernate.dialect.MySQLInnoDBDialect - - - MySQL con MyISAM org.hibernate.dialect.MySQLMyISAMDialect - - - Oracle (cualquier versión) org.hibernate.dialect.OracleDialect - - - Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect - - - Sybase org.hibernate.dialect.SybaseDialect - - - Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect - - - Microsoft SQL Server org.hibernate.dialect.SQLServerDialect - - - SAP DB org.hibernate.dialect.SAPDBDialect - - - Informix org.hibernate.dialect.InformixDialect - - - HypersonicSQL org.hibernate.dialect.HSQLDialect - - - Ingres org.hibernate.dialect.IngresDialect - - - Progress org.hibernate.dialect.ProgressDialect - - - Mckoi SQL org.hibernate.dialect.MckoiDialect - - - Interbase org.hibernate.dialect.InterbaseDialect - - - Pointbase org.hibernate.dialect.PointbaseDialect - - - FrontBase org.hibernate.dialect.FrontbaseDialect - - - Firebird org.hibernate.dialect.FirebirdDialect - - - -
- -
- - - Recuperación por Unión Externa (Outer Join Fetching) - - - Si tu base de datos soporta uniones externas del estilo ANSI, Oracle o Sybase, la - recuperación por unión externa aumentará - frecuentemente el rendimiento limitando el número de llamadas a la base de datos - (al costo de más trabajo posiblemente realizado por la base de datos misma). - La recuperación por unión externa permite que un grafo completo de objetos - conectados por asociaciones muchos-a-uno, uno-a-muchos, muchos-a-muchos y uno-a-uno sea - traído en una sola SELECT SQL. - - - - La recuperación por unión externa puede ser deshabilitada - globalmente estableciendo la propiedad - hibernate.max_fetch_depth a 0. - Un valor de 1 o mayor habilita la recuperación - por unión externa para asociaciones uno-a-uno y muchos-a-uno que - hayan sido mapeadas con fetch="join". - - - - Ver para más información. - - - - - - Flujos Binarios - - - Oracle limita el tamaño de arrays de byte - que puedan ser pasados a/desde su driver JDBC. Si deseas usar instancias - grandes de tipo binary o serializable, - debes habilitar hibernate.jdbc.use_streams_for_binary. - Esta es una propiedad a nivel de sistema solamente. - - - - - - Caché de segundo nivel y de lectura - - - Las propiedades prefijadas por hibernate.cache - te permiten usar un sistema de caché de segundo nivel - en el ámbito de un proceso o cluster con Hibernate. - Ver para más detalles. - - - - - - Sustitución de Lenguaje de Consulta - - - Puedes definir nuevos símbolos de consulta de Hibernate usando - hibernate.query.substitutions. Por ejemplo: - - - hibernate.query.substitutions true=1, false=0 - - - causaría que los símbolos true y false sean - traducidos a literales enteros en el SQL generado. - - - hibernate.query.substitutions toLowercase=LOWER - - - te permitiría renombrar la función LOWER de SQL. - - - - - - Hibernate statistics - - - Si habilitas hibernate.generate_statistics, Hibernate - expondrá un número de métricas que son útiles - al afinar un sistema en ejecución vía - SessionFactory.getStatistics(). Hibernate puede incluso ser - configurado para exponer estas estadísticas vía JMX. Lee el - Javadoc de las interfaces en org.hibernate.stats - para más información. - - - -
- - - Registros de mensajes (Logging) - - - Hibernate registra varios eventos usando commons-logging - de Apache. - - - - El servicio de commons-logging saldrá directamente ya sea a - Log4J (si incluyes log4j.jar in your classpath) o - JDK1.4 logging (al ejecutar bajo JDK1.4 o superior). Puedes descargar - Log4J desde http://logging.apache.org. Para usar - Log4J necesitarás colocar un fichero log4j.properties - en tu classpath. Un fichero de propiedades de ejemplo se distribuye con - Hibernate en el directorio src/. - - - - Recomendamos fuertemente que te familiarices con los registros de mensajes - de Hibernate. Se ha puesto un gran trabajo en hacer los registros de Hibernate - tan detallados como se puede, sin hacerlos ilegibles. Es un dispositivo esencial - en la resolución de problemas. Las categorías de registro - más interesantes son las siguientes: - - - - Categorías de Registro de Hibernate - - - - - - Categoría - Función - - - - - org.hibernate.SQL - Registra todas las sentencias DML de SQL a - medida que se ejecutan - - - org.hibernate.type - Registra todos los parámetros JDBC - - - org.hibernate.tool.hbm2ddl - Registra todas las sentencias DDL de SQL a - medida que se ejecutan - - - org.hibernate.pretty - - Registra el estado de todas las entidades (máximo - de 20 entidades) asociadas con la sesión en tiempo - de limpieza (flush) - - - - org.hibernate.cache - Registra toda la actividad del caché de segundo nivel - - - org.hibernate.transaction - Registra la actividad relacionada con la transacción - - - org.hibernate.jdbc - Registra toda adquisición de recursos JDBC - - - org.hibernate.hql.ast - Regista los ASTs de HQL y SQL, así como - otra información sobre análisis de consultas. - - - org.hibernate.secure - Registra todas las peticiones de autorización JAAS - - - org.hibernate - - Registra todo (mucha información, pero muy útil - para la resolución de problemas) - - - - -
- - - Al desarrollar aplicacinoes con Hibernate, casi siempre debes trabajar con - debug habilitado para la categoría org.hibernate.SQL - o, alternativamente, la propiedad hibernate.show_sql habilitada. - - - -
- - - Implementando una <literal>NamingStrategy</literal> - - - La interface org.hibernate.cfg.NamingStrategy te permite - especificar un "estándar de nombrado" para objetos de la base de datos - y elementos de esquema. - - - - Puedes proveer reglas para generar automáticamente identificadores de - base de datos a partir de identificadores JDBC o para procesar nombres - "lógicos" de columnas y tablas dados en el fichero de mapeo en nombres - "físicos" de columnas y tablas. Esta funcionalidad ayuda a reducir - la verborragia del documento de mapeo, eliminando ruido repetitivo - (prefijos TBL_, por ejemplo). La estrategia por defecto - usada por Hibernate mínima en absoluto. - - - - Puedes especificar una estrategia diferente llamando a - Configuration.setNamingStrategy() antes de agregar los mapeos: - - - - - - org.hibernate.cfg.ImprovedNamingStrategy - es una estrategia prefabricada que puede ser un punto de - partida útil para algunas aplicaciones. - - - - - - Fichero de configuración XML - - - Un enfoque alternativo de configuración es especificar una - configuración completa en un fichero llamado hibernate.cfg.xml. - Este fichero puede ser usado como un remplazo del fichero hibernate.properties o, - si ambos están presentes, para sobrescribir propiedades. - - - - El fichero de configuración XML se espera por defecto en la - raíz o tu CLASSPATH. He aquí un ejemplo: - - - - - - - - - - - - java:/comp/env/jdbc/MyDB - org.hibernate.dialect.MySQLDialect - false - - org.hibernate.transaction.JTATransactionFactory - - java:comp/UserTransaction - - - - - - - - - - - - -]]> - - - Como puedes ver, la ventaja de este enfoque es la externalización de los - nombres de los fichero de mapeo a configuración. El - hibernate.cfg.xml es también más conveniente - una vez que hayas afinado el caché de Hibernate. Observa que elección - tuya usar ya sea hibernate.properties o - hibernate.cfg.xml, ambos son equivalentes, excepto por los - beneficios de usar la sintaxis XML arriba mencionados. - - - - Con la configuración XML, arrancar Hibernate es tan simple como - - - - - - Puedes tomar un fichero XML diferente usando - - - - - - - - Integració con Servidores de Aplicaciones J2EE - - - Hibernate tiene los siguientes puntos de integración con la - infraestructura J2EE: - - - - - - Datasources manejados por contenedor: Hibernate puede usar - conexiones JDBC manejadas por el contenedor y provistas a través de JNDI. - Usualmente, un TransactionManager compatible con JTA y un - ResourceManager cuidan del manejo de transacciones (CMT), - esp. manejo de transacciones distribuídas a través de varios - datasources. Puedes también, por supuesto, demarcar los límites - de las transacciones programáticamente (BMT) o podrías querer usar - para esto la API opcional de Transaction de Hibernate para - mantener tu código portable. - - - - - - - - Ligamento Automático JNDI: Hibernate puede ligar sus - SessionFactory a JNDI después del arranque. - - - - - - - - Ligamento de Sesión JTA: - La Session de Hibernate puede ser ligada automáticamente - al ámbito de transacciones JTA si usas EJBs. Simplemente busca la - SessionFactory de JNDI y obtén la Session - actual. Deja que Hibernate cuide de limpiar y cerrar la Session - cuando se complete tu transacción JTA. La demarcación de transacción - es declarativa, en descriptores de despliegue de EJB. - - - - - - - - Despliegue JMX: Si tienes un servidor de aplicaciones capaz - de JMX (por ejemplo, JBoss AS), puedes optar por desplegar Hibernate como un MBean - manejado. Esto te ahorra el código de una línea de arranque para - construir tu SessionFactory desde una Configuration. - El contenedor arrancará tu HibernateService, e idealmente también - cuidará de las dependencias entre servicios (El datasource debe estar - disponible antes que arranque Hibernate, etc). - - - - - - Dependiendo de tu entorno, podrías tener que establecer la opción - de configuración hibernate.connection.aggressive_release - a true si tu servidor de aplicaciones muestra excepciones "connection containment". - - - - Configuración de la estrategia de transacción - - - La API de Session de Hibernate es independiente de cualquier - demarcación de transacción en tu arquitectura. Si dejas que Hibernate - use JDBC directamente, a través de un pool de conexiones. puedes comenzar y - acabar tus transacciones llamando la API de JDBC. Si ejecutas en un servidor de - aplicaciones J2EE, podréas querer usar transacciones manejadas por bean y - llamar la API de JTA y UserTransaction cuando sea necesario. - - - - Para mantener tu código portable entre estos dos (y otros) entornos recomendamos la API - de Transaction de Hibernate, que envuelve y oculta el sistema subyacente. - Tienes que especificar una clase fábrica para las instancias de Transaction - estableciendo la propiedad de configuración hibernate.transaction.factory_class - de Hibernate. - - - - Hay tres elecciones estándar (prefabricadas): - - - - - org.hibernate.transaction.JDBCTransactionFactory - - delega a transacciones de base de datos (JDBC) (por defecto) - - - - org.hibernate.transaction.JTATransactionFactory - - - delega a transacciones manejadas por contenedor si una transacción - existente estó por debajo en este contexto (ej. método de un - bean de sesión EJB), en otro caso una nueva transacción es - comenzada y se usan transacciones manejadas por bean. - - - - - org.hibernate.transaction.CMTTransactionFactory - - delega a transacciones JTA manejadas por contenedor - - - - - - Puedes definir también tus propias estrategias de transacción - (para un servicio de transacción CORBA, por ejemplo). - - - - Algunas funcionalidades en Hibernate (ej, el caché de segundo nivel, ligamento - automático de JTA y Session, etc.) requieren acceso al TransactionManager - de JTA en un entorno manejado. En un servidor de aplicaciones tienes que especificar - cómo Hibernate debe obtener una referencia al TransactionManager, - pues J2EE no estandariza un solo mecanismo: - - - - TransactionManagers de JTA - - - - - - Transaction Factory - Servidor de Aplicaciones - - - - - org.hibernate.transaction.JBossTransactionManagerLookup - JBoss - - - org.hibernate.transaction.WeblogicTransactionManagerLookup - Weblogic - - - org.hibernate.transaction.WebSphereTransactionManagerLookup - WebSphere - - - org.hibernate.transaction.WebSphereExtendedJTATransactionLookup - WebSphere 6 - - - org.hibernate.transaction.OrionTransactionManagerLookup - Orion - - - org.hibernate.transaction.ResinTransactionManagerLookup - Resin - - - org.hibernate.transaction.JOTMTransactionManagerLookup - JOTM - - - org.hibernate.transaction.JOnASTransactionManagerLookup - JOnAS - - - org.hibernate.transaction.JRun4TransactionManagerLookup - JRun4 - - - org.hibernate.transaction.BESTransactionManagerLookup - Borland ES - - - -
- -
- - - <literal>SessionFactory</literal> ligada a JNDI - - - Una SessionFactory de Hibernate ligada a JNDI puede simplificar - la obtención de la fábrica y la creación de nuevas - Sessions. Observa que esto no está relacionado a un - Datasource ligado a JNDI, simplemente ambos usan el mismo - registro! - - - - Si deseas tener la SessionFactory ligada a un espacio de nombres de JNDI, - especifica un nombre (ej. java:hibernate/SessionFactory) usando la - propiedad hibernate.session_factory_name. Si esta propiedad es omitida, - la SessionFactory no será ligada a JNDI (Esto es especialmente - útil en entornos con una implementació JNDI de sólo lectura por defecto, - ej. Tomcat.) - - - - Al ligar la SessionFactory a JNDI, Hibernate usará los valores de - hibernate.jndi.url, hibernate.jndi.class para instanciar - un contexto inicial. Si étos no se especifican, se usará el - InitialContext por defecto. - - - - Hibernate colocará automáticamente la SessionFactory - en JNDI después que llames a cfg.buildSessionFactory(). - Esto significa que tendrás al menos esta llamada en algún código - de arranque (o clase de utilidad) en tu aplicación, a menos qie uses el despliegue - JMX con el HibernateService (discutido luego). - - - - Si usas una SessionFactory de JNDI, un EJB o cualquier otra - clase puede obtener la SessionFactory usando una búsqueda - JNDI. Observa que esta configuración no es necesaria si usas la clase de ayuda - HibernateUtil introducida en el capítulo uno, que actúa - como un registro Singleton. Sin embargo, HibernateUtil es más - común en un entorno no manejado. - - - - - - Ligado automático de JTA y Session - - - Para entornos no manejados hemos sugerido HibernateUtil con una - SessionFactory estática, y administración de la - Session de Hibernate. Este enfoque no es fácil de usar - en un entorno EJB, al poder ejecutarse muchos EJBs dentro de la misma transacción - pero no en la misma hebra. Recomendados que ligues la SessionFactory - a JNDI en un entorno manejado. - - - - En vez de rodar tu propia utilidad de ThreadLocal, - usa el método getCurrentSession() en la - SessionFactory para obtener una Session - de Hibernate. Si no hubiese una Session de Hibernate en la - transacción JTA actual, se arrancará y asignará una. - Ambas opciones de configuración hibernate.transaction.flush_before_completion - y hibernate.transaction.auto_close_session, serán establecidas - automáticamente para cada Session que obtengas con - getCurrentSession(), de modo que éstas serán - limpiadas (flushed) y cerradas automáticamente cuando el contenedor complete - las transacciones JTA. - - - - Si tu, por ejemplo, usas el patrón de diseño DAO para escribir tu - capa de persistencia, todos los DAO's buscan la SessionFactory - cuando se necesite y abren la sesión "actual". No hay necesidad de pasar - las instancias de SessionFactory o Session - alrededor entre el código de control y el código DAO. - - - - - - Despliegue JMX - - - La línea cfg.buildSessionFactory() todavía tiene - que ser ejecutada en algun sitio para obtener una SessionFactory - en JNDI. Puedes hacer esto bien en un bloque inicializador static - (como aquel en HibernateUtil) o bien despliegas Hibernate como un - servicio manejado. - - - - Hibernate se distribuye con org.hibernate.jmx.HibernateService - para despliegue en un servidor de aplicaciones con capacidades JMX, como JBoss AS. - El despliegue y la configuracón reales son específicos del vendedor. - He aquí un jboss-service.xml de ejemplo para JBoss 4.0.x: - - - - - - - - - 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 fichero es desplegado en un directorio llamado META-INF y - empaquetado en un fichero JAR con la extensión .sar - (fichero de servicio). También necesitas empaquetar Hibernate, sus bibliotecas - de terceros requeridas, tus clases persistentes compiladas, así como tus ficheros de mapeo - en el mismo fichero. Tus beans de empresa (usualmente beans de sesión) pueden ser - mantenidos en su propio fichero JAR, pero debes incluir este fichero EJB JAR en el fichero - de servicio principal para obtener una unidad desplegable (en caliente). Consulta la documentación - de JBoss AS para más información sobre el servicio JMX y despliegue de EJB. - - - - -
- -
- diff --git a/documentation/manual/es-ES/src/main/docbook/modules/events.xml b/documentation/manual/es-ES/src/main/docbook/modules/events.xml deleted file mode 100644 index c5a70dfd3b..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/events.xml +++ /dev/null @@ -1,233 +0,0 @@ - - Interceptores y eventos - - - Frecuentemente es útil para la aplicación reaccionar a ciertos eventos que ocurran dentro de Hibernate. - Esto permite la implementación de ciertos tipos de funcionalidade genérica, y extensión de la - funcionalidad de Hibernate. - - - - Interceptores - - - La interface Interceptor provee callbacks desde la sesión a la aplicación - permitiendo a ésta última inspeccionar y/o manipular las propiedades de un objeto persistente - antes que sea salvado, actualizado, borrado o cargado. Un uso posible de esto es seguir la pista - de información de auditoría. Por ejemplo, el siguiente Interceptor establece - automáticamente el createTimestamp cuando un Auditable es - creado y actualiza la propiedad lastUpdateTimestamp cuando un - Auditable es acutalizado. - - - - - - El interceptor podría ser especificado cuando se crea la sesión: - - - - - - Puedes además establecer un interceptor a un nivel global, usando la Configuration: - - - - - - - - Sistema de eventos - - - Si tienes que reaccionar a eventos particulares en tu capa de persistencia, puedes también la - arquitectura de eventos de Hibernate3. El sistema de eventos puede ser usado - en adición o como un remplazo a los interceptores. - - - - Esencialmente todos los métodos de la interface Session se correlacionan - con un evento. Tienes un LoadEvent, un FlushEvent, etc - (consulta el DTD del fichero de configuración XML o el paquete org.hibernate.event - para la lista completa de tipos de evento definidos). Cuando se hace una petición de uno de estos - métodos, la Session de Hibernate genera un evento apropiado y se lo pasa - al oyente (listener) de eventos configurado para ese tipo. De fábrica, estos oyentes implementan - el mismo procesamiento en los que siempre resultan aquellos métodos. Sin embargo, eres libre de - implementar una personalización de una de las interfaces oyentes (es decir, el - LoadEvent es procesado por la implementación registrada de la interface - LoadEventListener), en cuyo caso su implementación sería responsable - de procesar cualquier petición load() hecha a la Session. - - - - Los oyentes deben ser considerados efectivamente singletons; quiere decir, que son compartidos - entre las peticiones, y por lo tanto no guardan ningún estado en variables de instancia. - - - - Un oyente personalizado debe implementar la interface apropiada para el evento que quiere procesar y/o - extender una de las clases base de conveniencia (o incluso los oyentes de eventos por defecto - usados por Hibernate de fábrica al ser éstos declarados non-final para este propósito). Los - oyentes personalizados pueden ser registrados programáticamente a través del objeto - Configuration, o especificados en el XML de configuración de Hibernate - (la declaración declarativa a través del fichero de propiedades no está soportada). - He aquí un ejemplo de un oyente personalizado de eventos load: - - - - - - Necesitas además una entrada de configuración diciéndole a Hibernate que use el - oyente en vez del oyente por defecto: - - - - - ... - - -]]> - - - En cambio, puedes registrarlo programáticamente: - - - - - - Los oyentes registrados declarativamente no pueden compartir instancias. Si el mismo nombre de clase es - usado en múltiples elementos <listener/>, cada referencia resultará en una instancia - separada de esa clase. Si necesitas la capacidad de compartir instancias de oyentes entre tipos de oyente - debes usar el enfoque de registración programática. - - - - ¿Por qué implementar una interface y definir el tipo espcífico durante la configuración? - Bueno, una implementación de oyente podría implementar múltiples interfaces de oyente - de eventos. Teniendo el tipo definido adicionalmente durante la registración lo hace más - fácil para activar o desactivar oyentes personalizados durante la configuración. - - - - - - Seguridad declarativa de Hibernate - - Usualmente, la seguridad declarativa en aplicaciones Hibernate es manejada en una capa de fachada - de sesión. Ahora, Hibernate3 permite que ciertas acciones sean permitidas vía JACC, y autorizadas vía - JAAS. Esta en una funcionalidad opcional construída encima de la arquitectura de eventos. - - - - Primero, debes configurar los oyentes de eventos apropiados, para habilitar el uso de - autorización JAAS. - - - - - -]]> - - - Seguido, aún en hibernate.cfg.xml, liga los permisos a roles: - - - -]]> - - - Los nombres de role son los roles entendidos por tu proveedor de JACC. - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/example_mappings.xml b/documentation/manual/es-ES/src/main/docbook/modules/example_mappings.xml deleted file mode 100644 index 376a0ce2c4..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/example_mappings.xml +++ /dev/null @@ -1,654 +0,0 @@ - - Ejemplo: Varios Mapeos - - - Este capítulo muestra mapeos de asociaciones más complejos. - - - - Empleador/Empleado - - - El siguiente modelo de la relación entre Employer y Employee - usa una clase de entidad real (Employment) para representar la asociación. - Esto se ha hecho esto porque podría haber más de un período de empleo para los mismos dos participantes. - Se usan componentes para modelar valores monetarios y nombres de empleado. - - - - - - - - - - - - - He aquí un documento de mapeo posible: - - - - - - - - employer_id_seq - - - - - - - - - - employment_id_seq - - - - - - - - - - - - - - - - - - - - - employee_id_seq - - - - - - - - - - -]]> - - - Y he aquí el esquema de tablas generado por SchemaExport. - - - - - - - - Autor/Obra - - - Considera el siguiente modelo de las relaciones entre Work, - Author y Person. Representamos la relación entre Work - y Author como una asociación muchos-a-muchos. Elegimos representar la relación entre - Author y Person como una asociación uno-a-uno. Otra posibilidad - hubiese sido que Author extendiera Person. - - - - - - - - - - - - - El siguiente documento de mapeo representa estas relaciones correctamente: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Hay cuatro tablas en este mapeo. works, authors y persons - tienen los datos de obra, autor y persona respectivamente. author_work es una tabla de - asociación enlazando autores a obras. He aquí el esquema de tablas, tal como fue generado por - SchemaExport. - - - - - - - - Cliente/Orden/Producto - - - Ahora considera un modelo de las relaciones entre Customer, - Order y LineItem y Product. - Hay una asociación uno-a-muchos entre Customer y Order, - pero, ¿cómo deberíamos representar Order / LineItem / Product? - He elegido mapear LineItem como una clase de asociación representando la - asociación muchos-a-muchos entre Order y Product. En Hibernate, - esto se llama un elemento compuesto. - - - - - - - - - - - - - El documento de mapeo: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - customers, orders, line_items y - products tienen los datos de cliente, orden, ítem de línea de orden y producto - respectivamente. Además line_items actúa como una tabla de asociación enlazando - órdenes con productos. - - - - - - - - Mapeos misceláneos de ejemplo - - - Todos estos ejemplos están tomados de la batería de pruebas de Hibernate. - Encontrarás muchos otros mapeos de ejemplo útiles allí. Mira en la carpeta - test de la distribución de Hibernate. - - - POR HACER: poner palabras alrededor de este material - - - Asociación uno-a-uno "Tipificada" - - - - name - 'HOME' - - - name - 'MAILING' - - - - - - - - - - - -]]> - - - - Ejemplo de clave compuesta - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ( select sum(li.quantity*p.price) - from LineItem li, Product p - where li.productId = p.productId - and li.customerId = customerId - and li.orderNumber = orderNumber ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ( select sum(li.quantity) - from LineItem li - where li.productId = productId ) - - - -]]> - - - - Muchos-a-muchos con atributo de clave compuesta compartido - - - - - - - - - - - - - org - - - - - - - - - - - - - - - - - - org - - - -]]> - - - - Discriminación basada en contenido - - - - - - - - - - case - when title is not null then 'E' - when salesperson is not null then 'C' - else 'P' - end - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - Asociaciones sobre claves alternativas - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/example_parentchild.xml b/documentation/manual/es-ES/src/main/docbook/modules/example_parentchild.xml deleted file mode 100644 index c8ca224347..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/example_parentchild.xml +++ /dev/null @@ -1,362 +0,0 @@ - - Ejemplo: Padre/Hijo - - - Una de las primerísimas cosas que los usuarios nuevos intentan hacer con Hibernate es modelar una relación de - tipo padre / hijo. Para esto hay dos enfoques diferentes. Por varias razones, el enfoque más conveniente, - especialmente para usuarios nuevos, es modelar tanto Parent como Child - como clases de entidad con una asociación <one-to-many> desde Parent - a Child. (El enfoque alternativo es declarar el Child como un - <composite-element>.) Ahora, resulta que la semántica por defecto de una asociación - uno a muchos (en Hibernate) es mucho menos cercana a la semántica usual de una relación padre / hijo que aquellas - de un mapeo de elementos compuestos. Explicaremos cómo usar una asociación uno a muchos bidireccional - con tratamiento en cascada para modelar una relación padre / hijo eficiente y elegantemente. - ¡No es para nada difícil! - - - - Una nota sobre las colecciones - - - Se considera que las colecciones de Hibernate son una parte lógica de la entidad que las posee; nunca de - las entidades contenidas. ¡Esta es una distinción crucial! Esto tiene las siguientes consecuencias: - - - - - - Cuando se quita / añade un objeto desde / a una colección, se incrementa el número de versión del - dueño de la colección. - - - - - Si un objeto que fue quitado de una colección es una instancia de un tipo de valor (por ejemplo, un - elemento compuesto), ese objeta cesará de ser persistente y su estado será completamente quitado de la - base de datos. Asimismo, añadir una instancia de tipo de valor a la colección causará que su estado - sea inmediatamente persistente. - - - - - Por otro lado, si se quita una entidad de una colección (una asociación uno-a-muchos o muchos-a-muchos), - no será borrado, por defecto. Este comportamiento es completamente consistente. ¡Un cambio en el - estado interno de otra entidad no hace desaparecer la entidad asociada! Asimismo, añadir una entidad a - una colección no causa que la entidad se vuelva persistente, por defecto. - - - - - - En cambio, el comportamiento por defecto es que al añadir una entidad a una colección se crea meramente - un enlace entre las dos entidades, mientras que al quitarla se quita el enlace. Esto es muy apropiado para - todos los tipos de casos. Donde no es para nada apropiado es en el caso de una relación padre / hijo. donde - la vida del hijo está ligada al ciclo de vida del padre. - - - - - - Uno-a-muchos bidirectional - - - Supón que empezamos con una asociación simple <one-to-many> desde - Parent a Child. - - - - - -]]> - - - Si ejecutásemos el siguiente código - - - - - - Hibernate publicaría dos sentencias SQL: - - - - - un INSERT para crear el registro de c - - - - un UPDATE para crear el enlace desde p a - c - - - - - - Esto no es sólo ineficiente, sino que además viola cualquier restricción NOT NULL en la - columna parent_id. Podemos reparar la violación de restricción de nulabilidad - especificando not-null="true" en el mapeo de la colección: - - - - - -]]> - - - Sin embargo, esta no es la solución recomendada. - - - El caso subyacente de este comportamiento es que el enlace (la clave foránea parent_id) - de p a c no es considerado parte del estado del objeto - Child y por lo tanto no es creada en el INSERT. De modo que la - solución es hacer el enlace parte del mapeo del Child. - - - ]]> - - - (Necesitamos además añadir la propiedad parent a la clase Child.) - - - - Ahora que la entidad Child está gestionando el estado del enlace, le decimos a la - colección que no actualice el enlace. Usamos el atributo inverse. - - - - - -]]> - - - El siguiente código podría ser usado para añadir un nuevo Child - - - - - - Y ahora, ¡Sólo se publicaría un INSERT de SQL! - - - - Para ajustar un poco más las cosas, podríamos crear un método addChild() en - Parent. - - - - - - Ahora, el código para añadir un Child se ve así - - - - - - - - Ciclo de vida en cascada - - - La llamada explícita a save() es aún molesta. Apuntaremos a esto usando tratamientos - en cascada. - - - - - -]]> - - - Esto simplifica el código anterior a - - - - - - Similarmente, no necesitamos iterar los hijos al salvar o borrar un Parent. - Lo siguiente quita p y todos sus hijos de la base de datos. - - - - - - Sin embargo, este código - - - - - - no quitará c de la base de datos; sólo quitará el enlace a p - (y causará una violación a una restricción NOT NULL). Necesitas borrar el hijo - explícitamente llamando a delete(). - - - - - - Ahora, en nuestro caso, un Child no puede existir realmente sin su padre. De modo que - si quitamos un Child de la colección, realmente queremos que sea borrado. Para esto, - debemos usar cascade="all-delete-orphan". - - - - - -]]> - - - Nota: aunque el mapeo de la colección especifique inverse="true", el tratamiento en - cascada se procesa aún al iterar los elementos de colección. De modo que si requieres que un objeto sea - salvado, borrado o actualizado en cascada, debes añadirlo a la colección. No es suficiente con simplemente - llamar a setParent(). - - - - - - Tratamiento en cascada y <literal>unsaved-value</literal> - - - Supón que hemos cargado un Parent en una Session, hemos hecho algunos - cambios en una acción de UI y deseamos hacer persistentes estos cambios en una nueva sesión llamando a - update(). El Parent contendrá una colección de hijos y, ya que - está habilitado el tratamiento en cascada, Hibernate necesita saber qué hijos están recién instanciados - y cuáles representan filas existentes en la base de datos. Asumamos que tanto Parent como - Child tienen propiedades identificadoras generadas de tipo Long. - Hibernate usará el identificador y el valor de la propiedad de versión/timestamp para determinar cuáles de - los hijos son nuevos. (Ver .) En Hibernate3, no es - más necesario especificar un unsaved-value explícitamente. - - - - The following code will update parent and child and insert - newChild. - - - - - - Bueno, todo eso está muy bien para el caso de un identificador generado, pero ¿qué de los - identificadores asignados y de los identificadores compuestos? Esto es más difícil, ya que Hibernate - no puede usar la propiedad identificadora para distinguir entre un objeto recién instanciado (con un - identificador asignado por el usuario) y un objeto cargado en una sesión previa. En este caso, Hibernate - bien usará la propiedad de versión o timestamp, o bien consultará realmente el caché de segundo nivel, - o bien, en el peor de los casos, la base de datos, para ver si existe la fila. - - - - - - - Conclusión - - - Hay que resumir un poco aquí y podría parecer confuso a la primera vez. Sin embargo, en la práctica, - todo funciona muy agradablemente. La mayoría de las aplicaciones de Hibernate usan el patrón - padre / hijo en muchos sitios. - - - - Hemos mencionado una alternativa en el primer párrafo. Ninguno de los temas anteriores existe en el caso - de los mapeos <composite-element>, que tienen exactamente la semántica de una - relación padre / hijo. Desafortunadamente, hay dos grandes limitaciones para las clases de elementos - compuestos: los elementos compuestos no pueden poseer sus propias colecciones, y no deben ser el hijo - de cualquier otra entidad que no sea su padre único. - - - - - \ No newline at end of file diff --git a/documentation/manual/es-ES/src/main/docbook/modules/example_weblog.xml b/documentation/manual/es-ES/src/main/docbook/modules/example_weblog.xml deleted file mode 100644 index 83e2c108c9..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/example_weblog.xml +++ /dev/null @@ -1,429 +0,0 @@ - - Ejemplo: Aplicación de Weblog - - - Clases Persistentes - - - Las clases persistentes representan un weblog, y un ítem enviado a un weblog. Van a ser modelados como una - relación padre/hijo estñndar, pero usaremos un bag ordenado, en vez de un conjunto (set). - - - - - - - - - - Mapeos de Hibernate - - - Los mapeos XML ahora deben ser absolutamente directos. - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - - Código Hibernate - - - La siguiente clase demuestra algunos de los tipos de cosas que podemos haces con estas clases, - usando Hibernate. - - - :minDate" - ); - - Calendar cal = Calendar.getInstance(); - cal.roll(Calendar.MONTH, false); - q.setCalendar("minDate", cal); - - result = q.list(); - tx.commit(); - } - catch (HibernateException he) { - if (tx!=null) tx.rollback(); - throw he; - } - finally { - session.close(); - } - return result; - } -}]]> - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/filters.xml b/documentation/manual/es-ES/src/main/docbook/modules/filters.xml deleted file mode 100644 index 8675dbdacc..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/filters.xml +++ /dev/null @@ -1,130 +0,0 @@ - - Filtrando datos - - - Hibernate3 provee un nuevo enfoque innovador para manejar datos con reglas de "visibilidad". - Un filtro de Hibernate es un filtro global, con nombre y parametrizado - que puede ser habilitado o deshabilitado para una sesión de Hibernate en particular. - - - - Filtros de Hibernate - - - Hibernate3 añade la habilidad de predefinir criterios de filtros y unir esos filtros tanto a - nivel de una clase como de una colección. Un criterio de filtro es la habilidad de definir una - cláusula de restricción muy similar al atributo existente "where" disponible en el elemento - class y varios elementos de colección. Excepto en que estos filtros pueden ser parametrizados. - La aplicación puede tomar la decisión en tiempo de ejecución de qué filtros deben estar - habilitados y cuáles deben ser sus parámetros. Los filtros pueden ser usados como vistas de - base de datos, pero parametrizados dentro de la aplicación. - - - - Para usar los filtros, éstos deben primero ser definidos y luego unidos a los elementos de mapeo - apropiados. Para definir un filtro, usa el elemento <filter-def/> dentro - de un elemento <hibernate-mapping/>: - - - - -]]> - - - Entonces este filtro puede ser unido a una clase: - - - - ... - -]]> - - - o a una colección: - - - - -]]> - - - o incluso a ambos (o muchos de cada uno) al mismo tiempo. - - - - Los métodos en Session son: enableFilter(String filterName), - getEnabledFilter(String filterName), y disableFilter(String filterName). - Por defecto, los filtros no están habilitados para una sesión dada; deben ser - habilitados explícitamente por medio del uso del método Session.enableFilter(), - que devuelve una instancia de la interface Filter. Usando el filtro simple definido - arriba, esto se vería así: - - - - - - Nota que los métodos en la interface org.hibernate.Filter permiten el encadenamiento de métodos - común en gran parte de Hibernate. - - - - Un ejemplo completo, usando datos temporales con un patrón efectivo de fechas de registro: - - - - - - - -... - - - -... - - - - - -... - - - - - -]]> - - - Entonces, en orden de asegurar que siempre tendrás de vuelta registros actualmente efectivos, - simplemente habilita el filtro en la sesión previo a recuperar los datos de empleados: - - - :targetSalary") - .setLong("targetSalary", new Long(1000000)) - .list(); -]]> - - - En el HQL de arriba, aunque sólo hemos mencionado explícitamente una restricción de salario en - los resultados, debido al filtro habilitado la consulta sólo devolverá empleados actualmente activos - que tengan un salario mayor que un millón de dólares. - - - - Nota: si planeas usar filtros con unión externa (outer joining) (bien a través de HQL, o bien - de recuperación de carga) sé cuidadoso en la dirección de expresión de la condición. Lo más seguro - es establecer esto para unión externa izquierda (left outer joining). En general, coloca el primer - parámetro seguido del nombre(s) de columna(s) después del operador. - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/inheritance_mapping.xml b/documentation/manual/es-ES/src/main/docbook/modules/inheritance_mapping.xml deleted file mode 100644 index 2d4140af9c..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/inheritance_mapping.xml +++ /dev/null @@ -1,464 +0,0 @@ - - Mapeo de Herencia - - - Las Tres Estrategias - - - Hibernate soporta las tres estrategias básicas de mapeo de herencia: - - - - - - tabla por jerarquía de clases - - - - - tabla por subclase - - - - - tabla por clase concreta - - - - - - En adición, Hibernate soporta un cuarto, ligeramente diferente tipo - de polimorfismo: - - - - - - polimorfismo implícito - - - - - - Es posible usar estrategias de mapeo diferentes para diferentes - ramificaciones de la misma jerarquía de herencia, y entonces usar - polimorfismo implícito para conseguir polimorfismo a través de - toda la jerarquía. Sin embargo, Hibernate no soporta la mezcla de - mapeos <subclass>, - y <joined-subclass> - y <union-subclass> bajo el mismo elemento - <class> raíz. Es posible mezclar juntas las - estrategias de tabla por jerarquía y tabla por subclase, bajo el mismo - elemento <class>, combinando los elementos - <subclass> y <join> - (ver debajo). - - - - Tabla por jerarquía de clases - - - Supón que tenemos una interface Payment, con - los implementadores CreditCardPayment, - CashPayment, ChequePayment. - El mapeo de tabla por jerarquía se vería así: - - - - - - - - - ... - - - ... - - - ... - - - ... - -]]> - - - Se requiere exactamente una tabla. Hay una gran limitación de esta estrategia de mapeo: - las columnas declaradas por las subclases, como CCTYPE, no pueden - tener restricciones NOT NULL. - - - - - - Tabla por subclase - - - Un mapeo de tabla por sublclase se vería así: - - - - - - - - ... - - - - ... - - - - ... - - - - ... - -]]> - - - Se requieren cuatro tablas. Las tres tablas de subclase tienen - asociaciones de clave primaria a la tabla de superclase (de modo - que en el modelo relacional es realmente una asociación uno-a-uno). - - - - - - Tabla por subclase, usando un discriminador - - - Observa que la implementación de Hibernate de tabla por subclase - no requiere ninguna columna discriminadora. Otros mapeadores - objeto/relacional usan una implementación diferente de tabla por - subclase que requiere una columna discriminadora de tipo en la tabla - de superclase. Este enfoque es mucho más difícil de implementar - pero discutiblemente más correcto desde un punto de vista relacional. - Si quisieras usar una columna discriminadora con la estrategia de - tabla por subclase, puedes combinar el uso de <subclass> - y <join>, como sigue: - - - - - - - - - ... - - - - - ... - - - - - - ... - - - - - - ... - - -]]> - - - la declaración opcional fetch="select" dice a Hibernate - que no recupere los datos de la subclase ChequePayment - usando una unión externa (outer join) al consultar la superclase. - - - - - - Mezclando tabla por jerarquía de clases con tabla por subclase - - - Puedes incluso mezclar las estrategias de tabla po jerarquía y tabla por - subclase usando este enfoque: - - - - - - - - - ... - - - - ... - - - - ... - - - ... - -]]> - - - Para cualquiera de estas estrategias de mapeo, una asociación polimórfica - a la clase raíz Payment es mapeada usando <many-to-one>. - - - ]]> - - - - - Tabla por clase concreta - - - Podríamos ir de dos maneras a la estrategia de mapeo de tabla por clase - concreta. La primera es usar <union-subclass>. - - - - - - - - ... - - - ... - - - ... - - - ... - -]]> - - - Están implicadas tres tablas. Cada tabla define columnas para todas las - propiedades de la clase, inccluyendo las propiedades heredadas. - - - - La limitación de este enfoque es que si una propiedad es mapeada en la - superclase, el nombre de columna debe ser el mismo en todas las tablas - de subclase. (Podríamos relajar esto en un lanzamiento futuro de Hibernate.) - La estrategia de generador de indentidad no está permitida en la herencia - de unión de subclase, de hecho la semilla de clave primaria tiene que ser - compartida a través de todas las subclases unidas de una jerarquía. - - - - - - Tabla por clase concreta, usando polimorfismo implícito - - - Un enfoque alternativo es hacer uso de polimorfismo implícito: - - - - - - - - ... - - - - - - - - ... - - - - - - - - ... -]]> - - - Nota que en ningún sitio mencionamos la interface Payment - explícitamente. Nota además que las propiedades de Payment - son mapeadas en cada una de las subclases. Si quieres evitar duplicación, - considera usar entidades XML. (por ejemplo, - [ <!ENTITY allproperties SYSTEM "allproperties.xml"> ] - en la declaración DOCTYPE y &allproperties; - en el mapeo). - - - - La desventaja de este enfoque es que Hibernate no genera UNIONs - de SQL al realizar consultas polimórficas. - - - - Para esta estrategia de mapeo, una asociación polimórfica a Payment - es mapeada generalmente usando <any>. - - - - - - - - -]]> - - - - - Mezclando polimorfismo implícito con otros mapeos de herencia - - - Hay una cosa más por notar acerca de este mapeo. Ya que las subclases se mapean - cada una en su propio elemento <class> (y ya que - Payment es sólo una interface), cada una de las subclases - podría ser parte de otra jerarquía de herencia! (Y todavía puedes seguir usando - consultas polimórficas contra la interface Payment.) - - - - - - - - - ... - - - - - - - - - ... - - - - ... - - - - - ... - -]]> - - - Una vez más, no mencionamos a Payment explícitamente. - Si ejecutamos una consulta contra la interface Payment - - por ejemplo, from Payment - Hibernate devuelve - automáticamente instancias de CreditCardPayment - (y sus subclases, ya que ellas también implementan Payment), - CashPayment y ChequePayment pero - no instancias de NonelectronicTransaction. - - - - - - - - Limitaciones - - - Existen ciertas limitaciones al enfoque de "polimorfismo implícito" en - la estrategia de mapeo de tabla por clase concreta. Existen limitaciones - algo menos restrictivas a los mapeos <union-subclass>. - - - - La siguiente tabla muestra las limitaciones de mapeos de tabla por - clase concreta, y de polmorfismo implícito, en Hibernate. - - - - Funcionalidades de mapeo de herencia - - - - - - - - - - - - Estrategia de herencia - muchos-a-uno polimórfica - uno-a-uno polimórfica - uno-a-muchos polimórfica - mushos-a-muchos polimórfica - load()/get() polimórficos - Consultas polimórficas - Uniones polimórficas - Recuperación por unión externa (outer join) - - - - - tabla por jerarquía de clases - <many-to-one> - <one-to-one> - <one-to-many> - <many-to-many> - s.get(Payment.class, id) - from Payment p - from Order o join o.payment p - soportada - - - tabla por subclase - <many-to-one> - <one-to-one> - <one-to-many> - <many-to-many> - s.get(Payment.class, id) - from Payment p - from Order o join o.payment p - soportada - - - tabla por clase concreta (union-subclass) - <many-to-one> - <one-to-one> - <one-to-many> (para inverse="true" solamente) - <many-to-many> - s.get(Payment.class, id) - from Payment p - from Order o join o.payment p - soportada - - - tabla por clase concreta (polimorfismo implícito) - <any> - no soportada - no soportada - <many-to-any> - s.createCriteria(Payment.class).add( Restrictions.idEq(id) ).uniqueResult() - from Payment p - no suportadas - no soportada - - - -
- -
- -
diff --git a/documentation/manual/es-ES/src/main/docbook/modules/performance.xml b/documentation/manual/es-ES/src/main/docbook/modules/performance.xml deleted file mode 100644 index bbbfa96064..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/performance.xml +++ /dev/null @@ -1,1334 +0,0 @@ - - Mejorando el rendimiento - - - Estrategias de recuperación - - - Una estrategia de recuperación es la estrategia que usará Hibernate para recuperar - los objetos asociados cuando la aplicación necesite navegar la asociación. Las estrategias de recuperación - pueden ser declaradas en los metadatos de mapeo O/R, o sobrescritas por una consulta HQL o - Criteria en particular. - - - - Hibernate3 define las siguientes estrategias de recuperación: - - - - - - Recuperación por unión (join fetching) - Hibernate recupera la - instancia asociada o colección en la misma SELECT, usando una - OUTER JOIN. - - - - - Recuperación por selección (select fetching) - se usa una segunda - SELECT para recuperar la entidad asociada o colección. A menos que - deshabilites explícitamente la recuperación perezosa especificando lazy="false", - la segunda selección sólo será ejecutada cuando realmente accedas a la asociación. - - - - - Recuperación por subselección (subselect fetching) - se usa una segunda - SELECT para recuperar las colecciones asociadas de todas las entidades - recuperadas en una consulta o recuperación previa. A menos que deshabilites explícitamente la - recuperación perezosa especificando lazy="false", esta segunda selección sólo - será ejecutada cuando realmente accedas a la asociación. - - - - - Recuperación en lote - una estrategia de optimización para la recuperación - por selección - Hibernate recupera un lote de instancias de entidad o colecciones en una sola - SELECT, especificando una lista de claves primarias o de claves foráneas. - - - - - - Hibernate también distingue entre: - - - - - - Recuperación inmediata - una asociación, colección o atributo es recuperado - inmediatamente, cuando el dueño es cargado. - - - - - Recuperación perezosa de colecciones - se recupera una colección cuando la - aplicación invoca una operación sobre la colección. (Esto es por defecto para las colecciones.) - - - - - Recuperación por proxy - se recupera una asociación monovaluada cuando se - invoca un método que no sea el getter del identificador sobre el objeto asociado. - - - - - Recuperación perezosa de atributos - se recupera un atributo o una asociación - monovaluada cuando se accede a la variable de instancia (requiere instrumentación del bytecode en - tiempo de ejecución). Este enfoque es raramente necesario. - - - - - - Aquí tenemos dos nociones ortogonales: cuándo se recupera la aplicación, - y cómo es recuperada (qué SQL es usado). ¡No las confundas! Usamos - fetch para afinar el rendimiento. Podemos usar lazy para - definir un contrato sobre qué datos están siempre disponibles en cualquier instancia separada de - una clase en particular. - - - - Trabajando con asociaciones perezosas - - - Por defecto, Hibernate3 usa una recuperación perezosa por selección para colecciones - y una recuperación por proxy perezosa para asociaciones monovaluadas. Estas políticas por - defecto tienen sentido para casi todas las asociaciones en casi todas las aplicaciones. - - - - Nota: si estableces hibernate.default_batch_fetch_size, Hibernate - usará la optimización de recuperación en lotes para recuperación perezosa (esta optimización también puede - ser habilitada a un nivel más granularizado). - - - - Sin embargo, la recuperación perezosa plantea un problema del que tienes que estar al tanto. Acceder - a una asociación perezosa fuera del contexto de una sesión de Hibernate abierta resultará en una - excepción. Por ejemplo: - - - - - - Ya que la colección de permisos no fue inicializada cuando se cerró la Session, - la colección no será capaz de cargar su estado. Hibernate no soporta la inicialización - perezosa de objetos separados. La solución es mover el código que lee de la colección - a justo antes que la transacción sea comprometida. - - - - Alternativamente, podríamos usar una colección no perezosa o asociación, especificando - lazy="false" para el mapeo de asociación. Sin embargo, está pensado - que la inicialización perezosa sea usada para casi todas las colecciones y asociaciones. - ¡Si defines demasiadas asociaciones no perezosas en tu modelo de objetos, Hibernate terminará - necesitando recuperar la base de datos entera en cada transacción! - - - - Por otro lado, frecuentemente necesitamos elegir la recuperación por unión (que es no perezosa - por naturaleza) en vez de la recuperación por selección en una transacción en particular. Veremos - ahora cómo personalizar la estrategia de recuperación. En Hibernate3, los mecanismos para elegir una - estrategia de recuperación son idénticas a las de las asociaciones monovaluadas y colecciones. - - - - - - Afinando las estrategias de recuperación - - - La recuperación por selección (la preestablecida) es extremadamente vulnerable a problemas de - selección N+1, de modo querríamos habilitar la recuperación por unión (join fetching) en el - documento de mapeo: - - - - - - - - ]]> - - - La estrategia de recuperación definida en el documento de mapeo afecta a: - - - - - - las recuperaciones vía get() o load() - - - - - las recuperaciones que ocurren implícitamente cuando se navega una asociación - (recuperación perezosa) - - - - - las consultas de Criteria - - - - - - Usualmente, no usamos el documento de mapeo para personalizar la recuperación. En cambio, mantenemos el - comportamiento por defecto, y lo sobrescribimos para una transacción en particular, usando - left join fetch en HQL. Esto le dice a Hibernate que recupere la asociación - tempranamente en la primera selección, usando una unión externa. En la API de consulta de - Criteria, usarías setFetchMode(FetchMode.JOIN). - - - - Si acaso lo deseases, podrías cambiar la estrategia de recuperación usada por - get() or load(); simplemente usa una consulta - Criteria, por ejemplo: - - - - - - (Esto es el equivalente de Hibernate de lo que otras soluciones ORM llaman un "plan de recuperación".) - - - - Una forma completamente diferente de evitar problemas con selecciones N+1 es usar el caché de - segundo nivel. - - - - - - Proxies de asociaciones de un solo extremo - - - La recuperación perezosa de colecciones está implementada usando la implementación de colecciones - persistentes propia de Hibernate. Sin embargo, se necesita un mecanismo diferente para un comportamiento - perezoso en las asociaciones de un solo extremo. La entidad objetivo de la asociación debe ser tratada - con proxies. Hibernate implementa proxies de inicialización perezosa para objetos persistentes usando - mejora del bytecode en tiempo de ejecución (por medio de la excelente biblioteca CGLIB). - - - - Por defecto, Hibernate3 genera proxies (en el arranque) para todas las clases persistentes y los usa - para habilitar la recuperación perezosa de asociaciones muchos-a-uno y - uno-a-uno. - - - - El fichero de mapeo puede declarar una interface a usar como interface de proxy para esa clase, - con el atributo proxy. Por defecto, Hibernate usa una subclase de la clase. - Nota que la clase tratada con proxies debe implementar un constructor por defecto con al - menos visibilidad de paquete. ¡Recomendamos este constructor para todas las clases persistentes! - - - - Hay algunos puntos a tener en cuenta al extender este enfoque a clases polimórficas, por ejemplo. - - - - ...... - - ..... - -]]> - - - Primero, las instancias de Cat nunca serán objeto de un cast a - DomesticCat, incluso aunque la instancia subyacente sea instancia de - DomesticCat: - - - - - - Segundo, es posible romper con el operador == de un proxy. - - - - - - Sin embargo, la situación no en absoluta tan mala como parece. Aunque tenemos ahora dos referencias - a objetos proxy diferentes, la instancia subyacente será aún el mismo objeto: - - - - - - Tercero, no debes usar un proxy CGLIB para una clase final o una clase - con algún método final. - - - - Finalmente, si tu objeto persistente adquiere cualquier recurso bajo instanciación - (por ejemplo, en inicializadores o constructores por defecto), entonces esos recursos - serán adquiridos también por el proxy. La clase del proxy es una subclase real de la clase - persistente. - - - - Estos problemas se deben a limitaciones fundamentales en el modelo de herencia única de Java. - Si deseas evitar estos problemas cada una de tus clases persistentes deben implementar una - interface que declare sus métodos de negocio. Debes especificar estas interfaces en el fichero - de mapeo. Por ejemplo: - - - - ...... - - ..... - -]]> - - - donde CatImpl implementa la interface Cat y - DomesticCatImpl implementa la interface DomesticCat. - Entonces load() o iterate() pueden devolver instancias de - Cat y DomesticCat. (Nota que list() - usualmente no devuelve proxies.) - - - - - - Las relaciones también son inicializadas perezosamente. Esto significa que debes declarar - cualquier propiedad como de tipo Cat, no CatImpl. - - - - Ciertas operaciones no requieren inicialización de proxies. - - - - - - equals(), si la clase persistente no sobrescribe equals() - - - - - hashCode(), si la clase persistente no sobrescribe - hashCode() - - - - - El método getter del identificador - - - - - - Hibernate detectará las clase persistentes que sobrescriban equals() o - hashCode(). - - - - - - Inicializando colecciones y proxies - - - Una LazyInitializationException será lanzada por Hibernate si una colección - o proxy sin inicializar es accedido fuera del ámbito de la Session, es decir, - cuando la entidad que posee la colección o que tiene la referencia al proxy esté en el estado - separada. - - - - A veces necesitamos asegurarnos que un proxy o colección esté inicializado antes de cerrar la - Session. Por supuesto, siempre podemos forzar la inicialización llamando a - cat.getSex() o cat.getKittens().size(), por ejemplo. - Pero esto es confuso a lectores del código y no es conveniente para código genérico. - - - - Los métodos estáticos Hibernate.initialize() y - Hibernate.isInitialized() proveen a la aplicación de una forma conveniente de - trabajar con colecciones o proxies inicializados perezosamente. - Hibernate.initialize(cat) forzará la inicialización de un proxy, - cat, en tanto su Session esté todavía abierta. - Hibernate.initialize( cat.getKittens() ) tiene un efecto similar para la colección - de gatitos. - - - - Otra opción es mantener la Session abierta hasta que todas las colecciones - y proxies necesarios hayan sido cargados. En algunas arquitecturas de aplicación, particularmente - en aquellas donde el código que accede a los datos usando Hibernate, y el código que los usa están - en capas de aplicación diferentes o procesos físicos diferentes, puede ser un problema asegurar que - la Session esté abierta cuando se inicializa una colección. Existen dos formas - básicas de tratar este tema: - - - - - - En una aplicación basada web, puede usarse un filtro de servlets para cerrar la - Session sólo bien al final de una petición de usuario, una - vez que el rendering de la vista esté completa (el patrón Sesión Abierta en - Vista (Open Session in View)). Por supuesto, estos sitios requieren una - fuerte demanda de corrección del manejo de excepciones de tu infraestructura de - aplicación. Es de una importancia vital que la Session esté - cerrada y la transacción terminada antes de volver al usuario, incluso cuando ocurra - una excepción durante el rendering de la página. Para este enfoque, el filtro de servlet tiene - que ser capaz de accceder la Session. Recomendamos que se use una variable - ThreadLocal para tener la Session actual (ver - el capítulo 1, , para una implementación de ejemplo). - - - - - En una aplciación con una grada de negocios separada, la lógica de negocio debe "preparar" - todas las colecciones que se vayan a necesitar por la grada web antes de volver. - Esto significa que la grada de negocios debe cargar todos los datos y devolver a la grada de - presentación web todos los datos que se requieran para un caso de uso en particular - ya inicializados. Usualmente, la aplicación llama a Hibernate.initialize() - para cada colección que se necesitará en la grada web (esta llamada debe ocurrir antes que la - sesión sea cerrada) o recupera la colección tempranamente usando una consulta de Hibernate con una - cláusula FETCH o una FetchMode.JOIN en - Criteria. Esto es usualmente más fácil si adoptas el patrón - Comando en vez de un Fachada de Sesión. - - - - - Puedes también adjuntar un objeto cargado previamente a una nueva Session - con merge() o lock() antes de acceder a colecciones - no inicializadas (u otros proxies). ¡No, Hibernate no, y ciertamente no - debe hacer esto automáticamente, ya que introduciría semánticas de transacción ad hoc! - - - - - - A veces no quieres inicializar una colección grande, pero necesitas aún alguna informacion sobre - ella (como su tamaño) o un subconjunto de los datos. - - - - Puedes usar un filtro de colecciones para obtener el tamaño de una colección sin inicializarla: - - - - - - El método createFilter() se usa también para recuperar eficientemente subconjuntos - de una colección sin necesidad de inicializar toda la colección: - - - - - - - - Usando recuperación en lotes - - - Hibernate puede hacer un uso eficiente de la recuperación en lotes, esto es, Hibernate puede cargar - muchos proxies sin inicializar si se accede a un proxy (o colecciones). La recuperación en lotes es una - optimización de la estrategia de recuperación por selección perezosa. Hay dos formas en que puedes afinar - la recuperación en lotes: a nivel de la clase o de la colección. - - - - La recuperación en lotes para clases/entidades es más fácil de entender. Imagina que tienes la siguiente - situación en tiempo de ejecución: Tienes 25 instancias de Cat cargadas en una - Session, cada Cat tiene una referencia a su owner, - una Person. La clase Person está mapeada con un proxy, - lazy="true". Si ahora iteras a través de todos los gatos y llamas a - getOwner() para cada uno, Hibernate por defecto ejecutará 25 sentencias - SELECT para traer los dueños tratados con proxies. Puedes afinar este comportamiento - especificando un batch-size en el mapeo de Person: - - - ...]]> - - - Hibernate ahora ejecutará sólo tres consultas, el patrón es 10, 10, 5. - - - - También puedes habilitar la recuperación en lotes para colecciones. Por ejemplo, si cada - Person tiene una colección perezosa de Cats, y hay 10 - personas actualmente cargadas en la Session, iterar a través de las 10 personas - generará 10 SELECTs, una para cada llamada a getCats(). - Si habilitas la recuperación en lotes para la colección de cats en el mapeo de - Person, Hibernate puede recuperar por adelantado las colecciones: - - - - - ... - -]]> - - - Con un batch-size de 3, Hibernate cargará 3, 3, 3, 1 colecciones en cuatro - SELECTs. Una vez más, el valor del atributo depende del número esperado de - colecciones sin inicializar en una Session en particular. - - - - La recuperación de coleccione en lotes es particularmente útil si tienes un árbol anidado de - ítems, es decir, el típico patrón de cuenta de materiales. (Aunque un conjunto - anidado o una ruta materializada podría ser una mejor opción - para árboles que sean de lectura en la mayoría de los casos.) - - - - - - Usando recuperación por subselección - - - Si una colección perezosa o proxy monovaluado tiene que ser recuperado, Hibernate los carga a todos, - volviendo a ejecutar la consulta original en una subselección. Esto funciona de la misma forma que - la recuperación en lotes, sin carga fragmentaria. - - - - - - - - Usando recuperación perezosa de propiedades - - - Hibernate3 soporta la recuperación perezosa de propiedades individuales. Esta técnica de optimización - es también conocida como grupos de recuperación (fetch groups). Por favor, nota - que éste es mayormente un aspecto de marketing, ya que en la práctica, optimizar lecturas de filas es - mucho más importante que la optimización de lectura de columnas. Sin embargo, cargar sólo algunas - propiedades de una clase podría ser útil en casos extremos, cuando tablas heredadas tienen cientos de - columnas y el modelo de datos no puede ser mejorado. - - - - Para habilitar la carga perezosa de propiedades, establece el atributo lazy en tus - mapeos de propiedades: - - - - - - - - - -]]> - - - ¡La carga perezosa de propiedades requiere la instrumentación del bytecode en tiempo - de construcción! Si tus clases persistentes no son mejoradas, Hibernate ignorará silenciosamente - la configuración perezosa de propiedades y caerá en recuperación inmediata. - - - - Para la instrumentación del bytecode, usa la siguiente tarea Ant: - - - - - - - - - - - - - - -]]> - - - Una forma diferente (¿mejor?) de evitar lecturas innecesarias de columnas, al menos para - transacciones de sólo lectura es usar las funcionalidades de proyección de consultas HQL o Criteria. - Esto evita la necesidad de procesar el bytecode en tiempo de construcción y ciertamente es una solución - preferida. - - - - Puedes forzar la usual recuperación temprana de propiedades usando fetch all properties - en HQL. - - - - - - - - El Caché de Segundo Nivel - - - Una Session de Hibernate es una caché de datos persistentes a nivel de transacción. - Es posible configurar un cluster o caché a nivel de JVM (a nivel de SessionFactory) - sobre una base de clase-a-clase o colección-a-colección. Puedes incluso enchufar una caché en cluster. - Sé cuidadoso. Las cachés nunca están al tanto de los cambios hechos por otra aplicación al almacén persistente - (aunque pueden ser configurados para expirar regularmente los datos en caché). - - - - Por defecto, Hibernate usa EHCache para caching a nivel de JVM. (El soporte a JCS ahora está despreciado - y será quitado en una futura versión de Hibernate.) Puedes elegir una implementación diferente estableciendo - el nombre de una clase que implemente org.hibernate.cache.CacheProvider usando la propiedad - hibernate.cache.provider_class. - - - - Proveedores de Caché - - - - - - - - - Caché - clase del Provedor - Tipo - Cluster Seguro - Caché de Consultas Soportado - - - - - Hashtable (no pensado para uso en producción) - org.hibernate.cache.HashtableCacheProvider - memoria - - - - - EHCache - org.hibernate.cache.EhCacheProvider - memoria, disco - - - - - OSCache - org.hibernate.cache.OSCacheProvider - memoria, disco - sí (invalidación en cluster) - - - - SwarmCache - org.hibernate.cache.SwarmCacheProvider - clusterizado (ip multicast) - sí (invalidación en cluster) - - - - TreeCache de JBoss - org.hibernate.cache.TreeCacheProvider - clusterizado (ip multicast), transaccional - sí (replicación) - sí (requiere sincronización de reloj) - - - -
- - - Mapeos de caché - - - El elemento <cache> de una mapeo de clase o colección tiene la siguiente - forma: - - - - - - - ]]> - - - - usage especifica la estrategia de caching: - transactional, - read-write, - nonstrict-read-write o - read-only - - - - - - - Alternativamente (¿preferiblemente?), puedes especificar los elementos - <class-cache> y <collection-cache> en - hibernate.cfg.xml. - - - - El atributo usage especifica una estrategia de concurrencia al - caché. - - - - - - Estrategia: sólo lectura (read only) - - - Si tu aplicación necesita leer pero nunca modificar las instancias de una clase persistente, - puede usarse un caché read-only. Esta es la mejor y más simple estrategia. - Es incluso perfectamente segura de usar en un cluster. - - - - - .... -]]> - - - - - - Estrategia: lectura/escritura (read/write) - - - Si la aplicación necesita actualizar datos, un caché read-write podría ser apropiado. - Esta estrategia de caché nunca debe ser usada si se requiere nivel de aislamiento serializable de - transacciones. Si el caché es usado en un entorno JTA, debes especificar la propiedad - hibernate.transaction.manager_lookup_class, mencionando una estrategia para obtener - el TransactionManager de JTA. En otros entornos, debes asegurarte que la transacción - esté completada cuando se llame a Session.close() o - Session.disconnect(). Si deseas usar esta estrategia en un cluster, debes asegurarte - que la implementación de caché subyacente soporta bloqueos. Los provedores de caché internos - predeterminados no no lo soportan. - - - - - .... - - - .... - -]]> - - - - - Estrategia: lectura/escritura no estricta (nonstrict read/write) - - - Si la aplicación necesita sólo ocasionalmente actualizar datos (es decir, es extremadamente inprobable - que dos transacciones intenten actualizar el mismo ítem simultáneamente) y no se requiere de un - aislamiento de transacciones estricto, un caché nonstrict-read-write podría ser - apropiado. Si se usa el caché en un entorno JTA, debes especificar - hibernate.transaction.manager_lookup_class. En otros entornos, debes asegurarte que la - transacción se haya completado cuando se llame a Session.close() o - Session.disconnect(). - - - - - - Estrategia: transaccional - - - La estrategia de caché transactional brinda soporte a provedores de cachés - completamente transaccionales como TreeCache de JBoss. Un caché así, puede sólo ser usado en un - entorno JTA y debes especificar hibernate.transaction.manager_lookup_class. - - - - - - Ninguno de los provedores de caché soporta todas las estrategias de concurrencia al caché. La siguiente - tabla muestra qué provedores son compatibles con qué estrategias de concurrencia. - - - - Soporte a Estrategia de Concurrencia a Caché - - - - - - - - - Caché - read-only - nonstrict-read-write - read-write - transactional - - - - - Hashtable (no pensado para uso en producción) - - - - - - - EHCache - - - - - - - OSCache - - - - - - - SwarmCache - - - - - - - JBoss TreeCache - - - - - - - -
- -
- - - Gestionando los cachés - - - Siempre que pases un objeto a save(), update() - o saveOrUpdate() y siempre que recuperes un objeto usando - load(), get(), list(), - iterate() o scroll(), ese objeto es agregado - al caché interno de la Session. - - - Cuando subsecuentemente se llame a flush(), el estado de ese objeto será - sincronizado con la base de datos. Si no quieres que ocurra esta sincronización o si estás - procesando un número enorme de objetos y necesitas gestionar la memoria eficientemente, - puede usarse el método evict() para quitar el objeto y sus colecciones - del caché de primer nivel. - - - - - - La Session también provee un método contains() para determinar - si una instancia pertenece al caché de la sesión. - - - - Para desahuciar (evict) todos los objetos del caché de sesión, llama a Session.clear(). - - - - Para el caché de segundo nivel, hay métodos definidos en SessionFactory para - desahuciar el estado en caché de una instancia, clase entera, instancia de colección o rol - enter de colección. - - - - - - El CacheMode controla cómo una sesión en particular interactúa con el caché de segundo - nivel. - - - - - - CacheMode.NORMAL - lee ítems desde y escribe ítems hacia el caché de segundo nivel - - - - - CacheMode.GET - lee ítems del caché de segundo nivel, pero no escribe al caché de - segundo nivel excepto al actualizar datos - - - - - CacheMode.PUT - escribe ítems al caché de segundo nivel, pero no lee del caché de segundo - nivel - - - - - CacheMode.REFRESH - escribe ítems al caché de segundo nivel, pero no lee del caché de - segundo nivel, saltándose el efecto de hibernate.cache.use_minimal_puts, forzando - un refresco del caché de segundo nivel para todos los ítems leídos de la base de datos - - - - - - Para navegar por los contenidos de una región de caché de segundo nivel o de consultas, usa la API de - Statistics: - - - - - - Necesitarás habilitar las estadísticas y, opcionalmente, forzar a Hibernate para que guarde las - entradas del caché en un formato más entendible por humanos: - - - - - - - - El Caché de Consultas - - - Los conjuntos resultado de consultas también pueden tratarse en caché. Esto sólo es útil para - consultas que se ejecutan frecuentemente con los mismos parámetros. Para usar el caché de consultas - primero debes habilitarlo: - - - - - - Esta configuración causa la creación de dos nuevas regiones de caché - una teniendo en caché - conjuntos resultado de consulta (org.hibernate.cache.StandardQueryCache), - el otro teniendo timestamps de las actualizaciones más recientes a tablas consultables - (org.hibernate.cache.UpdateTimestampsCache). Nota que el caché de consultas - no pone en caché el estado de las entidades reales en el conjunto resultado; sólo tiene en caché - valores indentificadores y resultados de tipo de valor. De modo que el caché de consultas siempre - debe ser usado en conjunción con el caché de segundo nivel. - - - - La mayoría de consultas no se benefician del tratamiento en caché, de modo que por defecto las - consultas no son tratadas en caché. Para habilitar el tratamiento en caché, llama a - Query.setCacheable(true). Esta llamada permite a la consulta buscar - resultados existentes en caché o agregar sus resultados al caché cuando se ejecuta. - - - - Si requieres un control finamente granularizado sobre las políticas de expiración del caché de - consultas, puedes especificar una región de caché con nombre para una consulta en particular - llamando a Query.setCacheRegion(). - - - - - - Si la consulta debe forzar un refresco de si región del caché de consultas, debes llamar a - Query.setCacheMode(CacheMode.REFRESH). Esto es particularmente útil en casos donde - los datos subyacentes pueden haber sido actualizados por medio de un proceso separado (es decir, - no modificados a través de Hibernate) y permite a la aplicación refrescar selectivamente conjuntos - resultado de consultas en particular. Esto es una alternativa más eficient al desahuciamiento de una - región del caché de consultas vía SessionFactory.evictQueries(). - - - - - - Entendiendo el rendimiento de Colecciones - - - Ya hemos llevado un buen tiempo hablando sobre colecciones. - En esta sección resaltaremos un par de temas más sobre cómo las colecciones - se comportan en tiempo de ejecución. - - - - Taxonomia - - Hibernate define tres tipos básicos de colecciones: - - - - colecciones de valores - - - asociaciones uno a muchos - - - asociaciones muchos a muchos - - - - - Esta clasificación distingue las varias tablas y relaciones de clave foránea pero no nos - dice absolutamente todo lo que necesitamos saber sobre el modelo relacional. Para entender - completamente la estructura relacional y las características de rendimiento, debemos considerar - la estructura de la clave primaria que es usada por Hibernate para actualizar o borrar filas de - colección. Esto sugiere la siguiente clasificación: - - - - - colecciones indexadas - - - conjuntos (sets) - - - bolsas (bags) - - - - - Todas las colecciones indexadas (mapas, listas, arrays) tienen una clave primaria - consistente de las columnas <key> y <index>. - En este caso las actualizaciones de colecciones son usualmente extremadamente eficientes. - La clave primaria puede ser indexada fácilmente y una fila en particular puede ser localizada - cuando Hibernate intenta actualizarla o borrarla. - - - - Los conjuntos (sets) tienen una clave primaria consistente en <key> - y columnas de elemento. Esto puede ser menos eficiente para algunos tipos de elemento de - colección, particularmente elementos compuestos o texto largo, o campos binarios. La base de datos - puede no ser capaz de indexar una clave primaria compleja eficientemente. Por otra parte, - para asociaciones uno a muchos o muchos a muchos, particularmente en el caso de identificadores - sintéticos, es probable que sólo sea tan eficiente. (Nota al márgen: si quieres que - SchemaExport realmente cree la clave primaria de un <set> - por ti, debes declarar todas las columnas como not-null="true".) - - - - Los mapeos de <idbag> definen una clave delegada, de modo que siempre - resulten eficientes de actualizar. De hecho, son el mejor caso. - - - - Los bags son el peor caso. Ya que un bag permite valores de elementos duplicados y no tiene - ninguna columna índice, no puede definirse ninguna clave primaria. Hibernate no tiene forma de - distinguir entre filas duplicadas. Hibernate resuelve este problema quitando completamente - (en un solo DELETE) y recreando la colección siempre que cambia. - Esto podría ser muy ineficiente. - - - - Nota que para una asociación uno-a-muchos, la "clave primaria" puede no ser la clave - primaria física de la tabla de base de datos; pero incluso en este caso, la clasificación - anterior es útil todavía. (Aún refleja cómo Hibernate "localiza" filas individuales de la - colección.) - - - - - - Las listas, mapas, idbags y conjuntos son las colecciones más eficientes de actualizar - - - Desde la discusión anterior, debe quedar claro que las colecciones indexadas y - (usualmente) los conjuntos permiten la operación más eficiente en términos de añadir, - quitar y actualizar elementos. - - - - Hay, discutiblemente, una ventaja más que las colecciones indexadas tienen sobre otros - conjuntos para las asociaciones muchos a muchos o colecciones de valores. Debido a la - estructura de un Set, Hibernate ni siquiera actualiza una fila con - UPDATE cuando se "cambia" un elemento. Los cambios a un Set - siempre funcionan por medio de INSERT y DELETE - (de filas individuales). Una vez más, esta consideración no se aplica a las asociaciones - uno a muchos. - - - - Después de observar que los arrays no pueden ser perezosos, podríamos concluir que las - listas, mapas e idbags son los tipos más eficientes de colecciones (no inversas), con los - conjuntos (sets) no muy por detrás. Se espera que los sets sean el tipo más común de colección - en las aplicaciones de Hibernate. Esto es debido a que la semántica de los sets es la más - natural en el modelo relacional. - - - - Sin embargo, en modelos de dominio de Hibernate bien dieñados, usualmente vemos que la mayoría - de las colecciones son de hecho asociaciones uno-a-muchos con inverse="true". - Para estas asociaciones, la actualización es manejada por el extremo muchos-a-uno de la asociación, - y las consideraciones de este tipo sobre el rendimiento de actualización de colecciones simplemente - no se aplican. - - - - - - Los Bags y las listas son las colecciones inversas más eficientes - - - Justo antes que tires a la zanja los bags para siempre, hay un caso en particular en el que - los bags son muchos más eficientes que los conjuntos. Para una colección con - inverse="true" (el idioma estándar de relaciones uno-a-muchos bidireccionales, - por ejemplo) ¡podemos añadir elementos a un bag o lista sin necesidad de inicializar (fetch) - los elementos del bag! Esto se debe a que Collection.add() o - Collection.addAll() siempre deben devolver true para un bag o List - (no como un Set). Esto puede hacer el siguiente código común mucho más rápido. - - - - - - - - Borrado de un solo tiro - - - Ocasionalmente, borrar los elementos de una colección uno a uno puede ser extremadamente ineficiente. - Hibernate no es completamente estúpido, de modo que sabe no hacer eso, en el caso de una colección - nueva-vacía (si has llamado a list.clear(), por ejemplo). En este caso, Hibernate - publicará una sola DELETE, ¡y listo! - - - - Supón que añadimos un solo elemento a una colección de tamaño veinte y luego quitamos dos elementos. - Hibernate publicará una sentencia INSERT y dos sentencias DELETE - (a menos que la colección sea un bag). Esto es ciertamente deseable. - - - - Sin embargo, supón que quitamos dieciocho elementos, dejando dos y luego añadimos tres nuevos elementos. - Hay dos formas posibles de proceder - - - - - borrar dieciocho filas una a una y luego insertar tres filas - - - quitar toda la colección (en un solo DELETE de SQL) e insertar todos los - cinco elementos actuales (uno a uno) - - - - - Hibernate no es lo suficientemente inteligente para saber que la segunda opción es probablemente más - rápida en este caso. (Y que sería probablemente indeseable para Hibernate ser tan inteligente; - este comportamiento podría confundir a disparadores de base de datos, etc.) - - - - Afortunadamente, puedes forzar este comportamiento (es decir, la segunda estrategia) en cualquier - momento descartando (es decir, desreferenciando) la colección original y devolviendo una colección - nuevamente instanciada con todos los elementos actuales. Esto puede ser muy útil y potente de vez en - cuando. - - - - Por supuesto, el borrado-de-un-solo-tiro no se aplica a colecciones mapeadas - inverse="true". - - - - - - - - Monitoreando el rendimiento - - - La optimización no es de mucho uso sin el monitoreo y el acceso a números de rendimiento. Hibernate provee - un rango completo de figuras sobre sus operaciones internas. Las estadísticas en Hibernate están disponibles - por SessionFactory. - - - - Monitoreando una SessionFactory - - - Puedes acceder a las métricas de SessionFactory de dos formas. - Tu primera opción es llamar a sessionFactory.getStatistics() y - leer o mostrar por pantalla la Statistics por ti mismo. - - - - Hibernate puede también usar JMX para publicar las métricas si habilitas el MBean - StatisticsService. Puede habilitar un solo MBean para todas tus - SessionFactory o una por fábrica. Mira el siguiente código para - ejemplos de configuración minimalistas: - - - - - - - - - POR HACER: Esto no tiene sentido: En el primer caso, recuperamos y usamos el MBean directamente. - En el segundo, debemos proporcionar el nombre JNDI en el que se guarda la fábrica de sesiones antes - de usarlo. Usa hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name") - - - Puedes (des)activar el monitoreo de una SessionFactory - - - - - en tiempo de configuración, establece hibernate.generate_statistics a - false - - - - - - - en tiempo de ejecución: sf.getStatistics().setStatisticsEnabled(true) - o hibernateStatsBean.setStatisticsEnabled(true) - - - - - - Las estadísticas pueden ser reajustadas programáticamente usando el método clear(). - Puede enviarse un resumen a un logger (nivel info) usando el método logSummary(). - - - - - - Métricas - - - Hibernate provee un número de métricas, desde información muy básica a la especializada - sólo relevante en ciertos escenarios. Todos los contadores disponibles se describen en la - API de la interface Statistics, en tres categorías: - - - - - Métricas relacionadas al uso general de Session usage, tales como - número de sesiones abiertas, conexiones JDBC recuperadas, etc, - - - - - Métricas relacionadas a las entidades, colecciones, consultas, y cachés como un todo. - (también conocidas como métricas globales). - - - - - Métricas detalladas relacionadas a una entidad, colección, consulta o región de caché - en particular. - - - - - - Por ejemplo, puedes comprobar el acceso, pérdida, y radio de colocación de entidades, colecciones - y consultas en el caché, y el tiempo promedio que necesita una consulta. Ten en cuenta que el número - de milisegundos está sujeto a aproximación en Java. Hibernate está pegado a la precisión de la JVM, - en algunas plataformas esto podría incuso ser tener sólo una exactitud de 10 segundos. - - - - Se usan getters simples para acceder a las métricas globales (es decir, no pegadas a una entidad, - colección, región de caché, etc, en particular). Puedes acceder a las métricas de una entidad, - colección, región de caché en particular a través de su nombre, y a través de su representación HQL - o SQL para las consultas. Por favor refiérete al Javadoc de la API de Statistics, - EntityStatistics, CollectionStatistics, - SecondLevelCacheStatistics, y QueryStatistics para más información. - El siguiente código muestra un ejemplo sencillo: - - - - - - Para trabajar sobre todas las entidades, colecciones, consultas y regiones de cachés, puedes recuperar la - lista de nombres de entidades, colecciones, consultas y regiones de cachés con los siguientes métodos: - getQueries(), getEntityNames(), - getCollectionRoleNames(), y getSecondLevelCacheRegionNames(). - - - - - - -
\ No newline at end of file diff --git a/documentation/manual/es-ES/src/main/docbook/modules/persistent_classes.xml b/documentation/manual/es-ES/src/main/docbook/modules/persistent_classes.xml deleted file mode 100644 index 980bf1af0a..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/persistent_classes.xml +++ /dev/null @@ -1,478 +0,0 @@ - - Clases Persistentes - - - Clases presistentes son clases en una aplicación que implementan las - entidades del problema de negocio (por ejemplo, Customer y Order en una - aplicación de comercio electrónico). No todas las instancias de una - clase persistente se considera que estén en el estado persistente, - una instancia puede en cambio ser transitoria o estar separada. - - - - Hibernate funciona mejor si las clases siguen algunas simples reglas, también - conocidas como el modelo de programación de Viejas Clases Java Planas - (Plain Old Java Object o POJO). Sin embargo, ninguna de estas reglas son - requerimientos rígidos. En cambio, Hibernate3 asume muy poco acerca de - la naturaleza de tus objetos persistentes. Puedes expresar un modelo de dominio en - otras formas: usando árboles de instancias de Map, - por ejemplo. - - - - Un ejemplo simple de POJO - - - La mayoría de aplicaciones Java requieren una clase - representando felinos. - - - - - - Aquí hay cuatro reglas principales a seguir: - - - - Implementa un constructor sin argumentos - - - Cat tiene un contructor sin argumentos. Todas las clases persistentes - deben tener un constructor por defecto (que puede no ser público) de modo que Hibernate - pueda instanciarlas usando Constructor.newInstance(). Recomendamos fuertemente tener - un constructor por defecto con al menos visibilidad de package para la - generación de proxies en tiempo de ejecución en Hibernate. - - - - - Provee una propiedad identificadora (opcional) - - - Cat tiene una propiedad llamada id. Esta - propiedad mapea a la columna clave primaria de la tabla de base de datos. La propiedad - podría llamarse cualquierCosa, y su tipo podría haber sido cualquier tipo - primitivo, cualquier tipo de "envoltura" primitivo, java.lang.String - o java.util.Date. (Si tu tabla de base de datos heredada tiene claves - compuestas, puedes incluso usar una clase definida por el usuario con propiedades de - estos tipos, ver la sección sobre identificadores compuestos luego.) - - - - La propiedad identificadora es estrictamente opcional. Puedes olvidarla y dejar que Hibernate - siga internamente la pista de los identificadores del objeto. Sin embargo, no recomendamos esto. - - - - De hecho, alguna funcionalidad está disponible sólo para clases que - declaran una propiedad identificadora: - - - - - - Reasociación transitiva de objetos separados (actualizaciones o - fusiones en cascada) - ver - - - - - Session.saveOrUpdate() - - - - - Session.merge() - - - - - - Recomendamos que declares propiedades identificadoras nombradas-consistentemente - en clases persistentes. Mas aún, recomendamos que uses un tipo nulable - (es decir, no primitivo). - - - - - Prefiere las clases no finales (opcional) - - Un aspecto central de Hibernate, proxies, depende de que - las clases persistentes sean ya no finales, o sean ya la implementación - de una interface que declare todos los métodos públicos. - - - Puedes persistir con Hibernate clases final que no implementen una - interface, pero no serás capaz de usar proxies para recuperación perezosa - de asociaciones, lo que limitará tus opciones para afinar el rendimiento. - - - Debes también evitar declarar métodos public final - en clases non-final. Si quieres usar una clase con un método public - final, debes deshabilitar explícitamente el uso de proxies estableciendo - lazy="false". - - - - - Declara métodos de acceso y modificación para los campos persistentes (opcional) - - Cat declara métodos de acceso para todos sus campos persistente. - Muchas otras herramientas ORM persisten directamente variables de instancia. Creemos que - es mejor proveer una indirección entre el esquema relacional y las estructuras internas de la clase. - Por defecto, Hibernate persiste propiedades del estilo JavaBeans, y reconoce nombres de método - de la forma getFoo, isFoo y setFoo. - Puedes cambiar a acceso directo a campos para propiedades en particular, de ser necesario. - - - - Las propiedades no necesitan ser declaradas públicas. Hibernate puede - persistir una propiedad con un par get / set protected o private. - - - - - - Implementando herencia - - - Una subclase puede a su vez observar la primera y segunda regla. Hereda su - propiedad identificadora de la superclase, Cat. - - - - - - - Implementando <literal>equals()</literal> y <literal>hashCode()</literal> - - - - Tienes que sobrescribir los métodos equals() y hashCode() - si : - - - - - piensas poner instancias de clases persistentes en un Set - (la forma recomendada de representar asociaciones multivaluadas) - y - - - - - piensas usar reasociación de instancias separadas. - - - - - - Hibernate garantiza la equivalencia de identidad persistente (fila de base de datos) y - identidad Java sólo dentro del ámbito de una sesión en particular. - De modo que en el momento que mezclamos instancias recuperadas en sesiones diferentes, - debemos implementar equals() y hashCode() si - deseamos tener una semántica significativa de Sets. - - - - La forma más 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 base de datos, por lo tanto son iguales (si ambos son agregados a un - Set, sólo tendremos un elemento en el Set). - Desafortunadamente, no podemos usar este enfoque con identificadores generados! Hibernate sólo - asignará valores identificadores a objetos que son persistentes, una instancia recién - creada no tendrá ningún valor identificador! Además, si una instancia no está - salvada y está actualmente en un Set, salvarla asignará un - valor identificador al objeto. Si equals() and hashCode() - están basados en el valor identificador, el código hash podría cambiar, - rompiendo el contrato de Set. Ver el sitio web de Hibernate para una - discusión completa de este problema. Observa que esto no es una incidencia de Hibernate, - sino la semántica normal de Java de identidad de objeto e igualdad. - - - - Recomendamos implementar equals() y hashCode() - usando igualdad de clave de negocio (Business key equality). - Igualdad de clave de negocio significa que el método equals() - compara sólo las propiedades que forman la clave de negocio, una clave que podría - identificar nuestra instancia en el mundo real (una clave candidata - natural): - - - - - - Nota que una clave de negocio no tiene que ser tan sólida como - una clave primaria candidata de base de datos (ver - ). Las propiedades inmutables o - únicas son usualmente buenas candidatas para una clave de negocio. - - - - - - Modelos dinámicos - - - Ten en cuenta que las siguientes funcionalidades están - consideradas actualmente experimentales y pueden cambiar en el futuro - cercano. - - - - Las entidades persistentes no necesariamente tienen que estar representadas - como clases POJO o como objetos JavaBean en tiempo de ejecución. Hibernate - soporta además modelos dinámicos (usando Maps de - Maps en tiempo de ejecución) y la representación - de entidades como árboles de DOM4J. Con este enfoque no escribes clases - persistentes, sólo ficheros de mapeo. - - - - Por defecto, Hibernate funciona en modo POJO normal. Puedes establecer una - representación de entidad por defecto para una SessionFactory - en particular usando la opción de configuración - default_entity_mode - (ver ). - - - - Los siguientes ejemplos demuestran la representación usando - Maps. Primero, en el fichero de mapeo, - tiene que declararse un entity-name en vez de - (o como agregado a) un nombre de clase: - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Ten en cuenta que aunque las asociaciones se declaran usando nombres - de clase objetivo, el tipo objetivo de una asociación puede - ser además una entidad dinámica en vez de un POJO. - - - - Después de establecer el modo de entidad por defecto a - dynamic-map para la SessionFactory, - podemos trabajar en tiempo de ejecución con Maps - de Maps: - - - - - - Las ventajas de un mapeo dinámico es rápido tiempo de ciclo - de prototipado sin la necesidad de implementación de clases de entidad. - Sin embargo, pierdes chequeo de tipos en tiempo de compilación y - muy probablemente tratarás con muchas excepciones en tiempo de ejecución. - Gracias al mapeo de Hibernate, el esquema de base de datos puede estar facilmente - sano y normalizado, permitiendo agregar una implementación apropiada del - modelo de dominio más tarde. - - - - Los modos de representación de entidad pueden ser establecidos - por Session: - - - - - - - Por favor, ten en cuenta que la llamada a getSession() - usando un EntityMode está en la API de - Session, no en la de SessionFactory. - De esta forma, la nueva Session comparte la conexión - JDBC, transacción y otra información de contexto. Esto significa - que no tienes que llamar a flush() ni a close() - en la Session secundaria, y tembién dejar el manejo - de la transacción y de la conexión a la unidad de trabajo primaria. - - - - Puede encontrarse más información sobre las capacidades de - representación XML en . - - - - - - PORHACER: Documentar el framework de extensiones del usuario en los paquetes - de propiedad y proxies. - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/query_criteria.xml b/documentation/manual/es-ES/src/main/docbook/modules/query_criteria.xml deleted file mode 100644 index 8bdbf5def3..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/query_criteria.xml +++ /dev/null @@ -1,431 +0,0 @@ - - Consultas por Criterios - - - Acompaña a Hibernate una API de consultas por criterios intuitiva y extensible. - - - - Creando una instancia de <literal>Criteria</literal> - - - La interface org.hibernate.Criteria representa una consulta contra - una clase persistente en particular. La Session es una fábrica de instancias - de Criteria. - - - - - - - - Estrechando el conjunto resultado - - - Un criterio individual de consulta es una instancia de la interface - org.hibernate.criterion.Criterion. La clase - org.hibernate.criterion.Restrictions define métodos de fábrica para obtener ciertos tipos - prefabricados de Criterion. - - - - - - Las restricciones pueden ser agrupadas lógicamente. - - - - - - - - Hay un gran rango de tipos de criterio prefabricados (subclases de Restrictions), - pero uno que es especialmente útil te deja especificar SQL directamente. - - - - - - El sitio {alias} será remplazado por el alias de fila de la entidad consultada. - - - - Un enfoque alternativo para obtener un criterio es tomarlo de una instancia de - Property. Puedes crear una Property llamando a - Property.forName(). - - - - - - - - Ordenando los resultados - - - Puedes ordenar los resultados usando org.hibernate.criterion.Order. - - - - - - - - - - Asociaciones - - - Puedes especificar fácilmente restricciones sobre las entidades relacionadas al navegar asociaciones - usando createCriteria(). - - - - - - nota que el segundo createCriteria() devuelve una nueva instancia de - Criteria, que hace referencia a los elementos de la colección - kittens. - - - - La siguiente forma alternativa es útil en ciertas circunstancias. - - - - - - (createAlias() no crea una nueva instancia de - Criteria.) - - - - ¡Observa que las colecciones de gatitos tenidas por las instancias de Cat devueltas - por las dos consultas previas no están prefiltradas por los criterios! Si deseas - recuperar sólo los gatitos que emparejen los criterios, debes usar returnMaps(). - - - - - - - - Recuperación dinámica de asociaciones - - - Puedes especificar la semántica de recuperación de asociaciones en tiempo de ejecución usando - setFetchMode(). - - - - - - Esta consulta recuperará tanto mate como kittens por - unión exterior (outer join). Ver para más información. - - - - - - Consultas por ejemplos - - - La clase org.hibernate.criterion.Example te permite construir un criterio de consulta - a partir de una instancia dada. - - - - - - Las propiedades de versión, los identificadores y las asociaciones son ignorados. Por defecto, - las propiedades valuadas a nulo son excluídas. - - - - Puedes ajustar cómo se aplica el Example. - - - - - - Puedes incluso usar ejemplos para colocar criterios sobre objetos asociados. - - - - - - - - Proyecciones, agregación y agrupamiento - - La clase org.hibernate.criterion.Projections es una fábrica de instancias de - Projection. Aplicamos una proyección a una consulta llamando a - setProjection(). - - - - - - - - No es necesario ningún "group by" explícito en una consulta por criterios. - Ciertos tipos de proyecciones son definidos para ser proyecciones agrupadas, - que además aparecen en la cláusula SQL group by. - - - - Puede opcionalmente asignarse un alias a una proyección, de modo que el valor proyectado pueda - ser referido en restricciones u ordenamientos. Aquí hay dos formas diferentes de hacer esto: - - - - - - - - Los métodos alias() y as() simplemente envuelven una instancia - de proyección en otra instancia de Projection con alias. Como un atajo, puedes asignar - un alias cuando agregas la proyección a una lista de proyecciones: - - - - - - - - Puedes también usar Property.forName() para expresar proyecciones: - - - - - - - - - - Consultas y subconsultas separadas - - La clase DetachedCriteria te deja crear una consulta fuera del ámbito de una sesión, - y entonces ejecutarla luego usando alguna Session arbitraria. - - - - - - También una DetachedCriteria puede usarse para expresar una subconsulta. - Las instancias de Criterion implicando subconsultas pueden obtenerse vía Subqueries o - Property. - - - - - - - - Incluso son posibles las subconsultas correlacionadas: - - - - - - - - - - Consultas por identificador natural - - - Para la mayoría de consultas, incluyendo las consultas por criterios, el caché de consulta no es - muy eficiente, debido a que la invalidación del caché de consulta ocurre demasiado frecuentemente. - Sin embargo, hay un tipo especial de consulta donde podemos optimizar el algoritmo de invalidación - de caché: búsquedas por una clave natural constante. En algunas aplicaciones, este tipo de consulta, - ocurre frecuentemente. La API de criterios brinda especial provisión para este caso de uso. - - - - Primero, debes mapear la clave natural de tu entidad usando - <natural-id>, y habilitar el uso del caché de segundo nivel. - - - - - - - - - - - - -]]> - - - Nota que esta funcionalidad no está pensada para uso con entidades con claves naturales - mutable. - - - - Seguido, habilita el caché de consulta de Hibernate. - - - - Ahora, Restrictions.naturalId() nos permite hacer uso de el algoritmo de caché - más eficiente. - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/query_hql.xml b/documentation/manual/es-ES/src/main/docbook/modules/query_hql.xml deleted file mode 100644 index bd6df664b4..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/query_hql.xml +++ /dev/null @@ -1,1107 +0,0 @@ - - HQL: El Lenguaje de Consulta de Hibernate - - - Hibernate está equipado con un lenguaje de consulta extremadamente potente que - (intencionalmente en absoluto) se parece muchísimo a SQL. Pero no te engañes por la sintaxis; - HQL es completamente orientado a objetos, entendiendo nociones como herencia, polimorfismo - y asociación. - - - - Sensibilidad a Mayúsculas - - - Las consultas son insensibles a mayúsculas, excepto para nombres de clases Java y propiedades. De modo que - SeLeCT es lo mismo que sELEct e igual a SELECT, - pero org.hibernate.eg.FOO no lo es a org.hibernate.eg.Foo y - foo.barSet no es igual a foo.BARSET. - - - - Este manual usa palabras clave HQL en minúsculas. Algunos usuarios encuentran las consultas con - palabras clave en mayúsculas más leíbles, pero encontramos esta convención fea cuando se encaja - en código Java. - - - - - - La cláusula from - - - La consulta más simple posible de Hibernate es de la forma: - - - - - - que simplemente devuelve todas las instancias de la clase eg.Cat. - Usualmente no necesitamos cualificar el nombre de la clase, ya que auto-import - está por defecto. De modo que casi siempre escribimos solamente: - - - - - - La mayoría del tiempo, necesitarás asignar un alias, ya que querrás referirte al - Cat en otras partes de la consulta. - - - - - - Esta consulta asigna el alias cat a las instancias de Cat, - de modo que podríamos usar ese alias luego en la consulta. La palabra clave as - es opcional; también podríamos escribir: - - - - - - Pueden aparecer múltiples clases, resultando en un producto cartesiano o unión "cruzada" (cross join). - - - - - - - Se considera buena práctica el nombrar los alias de consulta usando una inicial en minúsculas, - consistente con los estándares de nombrado de Java para variables locales - (por ejemplo, domesticCat). - - - - - - Asociaciones y uniones (joins) - - - Podemos también asignar aliases a entidades asociadas, e incluso a elementos de una colección de valores, - usando una join. - - - - - - - - - - Los tipos de join soportados son prestados de ANSI SQL - - - - - - inner join - - - - - left outer join - - - - - right outer join - - - - - full join (no útil usualmente) - - - - - - Las construcciones inner join, left outer join y - right outer join pueden ser abreviadas. - - - - - - Puedes proveer condiciones de unión extra usando la palabra clave with de HQL. - - - 10.0]]> - - - En adición, un "fetch" join permite a las asociaciones o colecciones de valores ser inicializadas - junto a sus objetos padres, usando una sola selección. Esto es particularmente útil en el case de una - colección. Efectivamente sobrescribe el outer join y las declaraciones perezosas (lazy) del fichero - de mapeo para asociaciones y colecciones. Ver para más - información. - - - - - - Usualmente a un fetch join no se necesita asignársele un alias, porque los objetos asociados no deben - ser usados en la cláusula where (ni en cualquier otra cláusula). Además, los objetos - asociados no son devueltos directamente en los resultados de consulta. En cambio, pueden ser accedidos - vía el objeto padre. La única razón por la que necesitaríamos un alias es estamos uniendo recursivamente - otra colección: - - - - - - Nota que la construcción fetch no puede usarse en consultas llamadas usando - scroll() o iterate(). Ni debe usarse fetch - junto con setMaxResults() o setFirstResult(). Tampoco puede usarse - fetch junto a una condición with ad hoc. Es posible crear - un producto cartesiano trayendo por join más de una colección en una colección, así que ten cuidado en - este caso. Traer por join múltiples roles de colección también da a veces resultados inesperados para mapeos - de bag, así que sé cuidadoso sobre cómo formular tus consultas en este caso. Finalmente, nota que - full join fetch y right join fetch no son significativos. - - - - Si estás usando recuperación perezosa a nivel de propiedad (con instrumentación de bytecode), es posible - forzar a Hibernate a traer las propiedades perezosas inmediatamente (en la primera consulta) usando - fetch all properties. - - - - - - - - - La cláusula select - - - La cláusula select escoge qué objetos y propiedades devolver in el conjunto resultado - de la consulta. Considera: - - - - - - La consulta seleccionará mates de otros Cats. - Realmente, puedes expresar esta consulta en un forma más compacta como: - - - - - - Las consultas pueden devolver propiedades de cualquier tipo de valor incluyendo propiedades de - tipo componente: - - - - - - - - Las consultas pueden devolver múltiples objetos y/o propiedades como un array de tipo - Object[], - - - - - - o como una List, - - - - - - o como un objeto real Java de tipo seguro, - - - - - - asumiendo que la clase Family tiene un constructor apropiado. - - - - Puedes asignar aliases para seleccionar expresiones usando as: - - - - - - Esto es lo más útil cuando se usa junto con select new map: - - - - - - Esta consulta devuelve un Map de aliases a valores seleccionados. - - - - - - Funciones de agregación - - - Las consultas HQL pueden incluso devolver resultados de funciones de agregación sobre propiedades: - - - - - - - - Las funciones de agregación soportadas son - - - - - - avg(...), sum(...), min(...), max(...) - - - - - count(*) - - - - - count(...), count(distinct ...), count(all...) - - - - - - Puedes usar operadores aritméticos, concatenación, y funciones SQL reconocidas en la cláusula select: - - - - - - - - Las palabras clave distinct y all pueden ser usadas y tienen las misma - semántica que en SQL. - - - - - - - - Consultas polimórficas - - - Una consulta como: - - - - - - devuelve instancias no sólo de Cat, sino también de subclases como - DomesticCat. Las consultas de Hibernate pueden mencionar cualquier - clase o interface Java en la cláusula from. La consulta devolverá instancias de todas - las clases persistentes que extiendan esa clase o implementen la interface. La siguiente consulta devolvería - todos los objetos persistentes. - - - - - - La interface Named podría ser implementada por varias clases persistentes: - - - - - - Nota que estas dos últimas consultas requerirán más de un SELECT SQL. Esto significa - que la cláusula order by no ordenará correctamente todo el conjunto resultado. - (Significa además que no puedes llamar estas consulta usando Query.scroll().) - - - - - - La cláusula where - - - La cláusula where te permite estrechar la lista de instancias devueltas. Si no existe ningún alias. - puedes referirte a las propiedades por nombre: - - - - - - Si existe un alias, usan un nombre cualificado de propiedad: - - - - - - devuelve las instancias de Cat llamadas 'Fritz'. - - - - - - devolverá todas las instancias de Foo para las cuales exista una instancia - de bar con una propiedad date igual a la propiedad - startDate del Foo. Las expresiones de ruta compuestas hacen - la cláusula where extremadamente potente. Considera: - - - - - - Esta consulta se traduce en una consulta SQL con una unión de tabla (interna). Si fueses a escribir algo como - - - - - - terminarías con una consulta que requeriría cuatro uniones de tablas en SQL. - - - - El operador = puede ser usado para comparar no sólo propiedades, sino también instancias: - - - - - - - - La propiedad especial (en minúsculas) id puede ser usada para referenciar el identificador - único de un objeto. (También puedes usar su nombre de propiedad.) - - - - - - La segunda consulta es eficiente. ¡No se requiere ninguna unión de tablas! - - - - También pueden ser usadas las propiedades de identificadores compuestos. Supón que Person - tiene un identificador compuesto consistente en country y medicareNumber. - - - - - - - - Una vez más, la segunda consulta no requiere ninguna unión de tablas. - - - - Asimismo, la propiedad especial class acccede al valor discriminador de una instancia en - el caso de persistencia polimórfica. Un nombre de clase Java embebido en la cláusula where será - traducido a su valor discriminador. - - - - - - Puedes también especificar propiedades de componentes o tipos compuestos de usuario (y de componentes - de componentes, etc). Nunca intentes usar una expresión de ruta que termine en una propiedad de tipo - componente (al contrario de una propiedad de un componente). Por ejemplo, si store.owner - es una entidad con un componente address - - - - - - Un tipo "any" tiene las propiedades especiales id y class, - permiténdonos expresar un join en la siguiente forma (donde AuditLog.item es una - propiedad mapeada con <any>). - - - - - - Nota que log.item.class y payment.class harían referencia a - los valores de columnas de base de datos completamente diferentes en la consulta anterior. - - - - - - Expresiones - - - Las expresiones permitidas en la cláusula where incluyen la mayoría del tipo de cosas - que podrías escribir en SQL: - - - - - - operadores matemáticos +, -, *, / - - - - - operadores de comparación binarios =, >=, <=, <>, !=, like - - - - - operadores lógicos and, or, not - - - - - Paréntesis ( ), indicando agrupación - - - - - in, - not in, - between, - is null, - is not null, - is empty, - is not empty, - member of y - not member of - - - - - Caso "simple", case ... when ... then ... else ... end, - y caso "buscado", case when ... then ... else ... end - - - - - concatenación de cadenas ...||... o concat(...,...) - - - - - current_date(), current_time(), - current_timestamp() - - - - - second(...), minute(...), - hour(...), day(...), - month(...), year(...), - - - - - Cualquier función u operador definido por EJB-QL 3.0: substring(), trim(), - lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod() - - - - - coalesce() y nullif() - - - - - str() para convertir valores numéricos o temporales a una cadena legible. - - - - - cast(... as ...), donde el segundo argumento es el nombre de un tipo Hibernate - , y extract(... from ...) si cast() y - extract() fuesen soportados por la base de datos subyacente. - - - - - - - la función index() de HQL, que se aplica a alias de una colección - indexada unida. - - - - - funciones de HQL que tomen expresiones de ruta valuadas en colecciones: size(), - minelement(), maxelement(), minindex(), maxindex(), junto a las funciones especiales - elements() and indices que pueden ser cuantificadas usando - some, all, exists, any, in. - - - - - - Cualquier función escalar SQL soportada por la base de datos como sign(), - trunc(), rtrim(), sin() - - - - - parámetros posicionales JDBC ? - - - - - parámetros con nombre :name, :start_date, :x1 - - - - - literales SQL 'foo', 69, 6.66E+2, - '1970-01-01 10:00:01.0' - - - - - constantes Java public static final eg.Color.TABBY - - - - - - in y between pueden usarse como sigue: - - - - - - - - y pueden escribirse las formas negadas - - - - - - - - Asimismo, is null y is not null pueden ser usadas para comprobar - valores nulos. - - - - Los booleanos pueden ser fácilmente usados en expresiones declarando substituciones de consulta HQL - en la configuración de Hibernate: - - - true 1, false 0]]> - - - Esto remplazará las palabras clave true y false con los literales - 1 y 0 en el SQL traducido de este HQL: - - - - - - Puedes comprobar el tamaño de una colección con la propiedad especial size, o la función - especial size(). - - - 0]]> - - 0]]> - - - Para colecciones indexadas, puedes referirte a los índices máximo y mínimo usando las funciones - minindex y maxindex. Similarmente, puedes referirte a los elementos - máximo y mínimo de una colección de tipo básico usando las funciones - minelement y maxelement. - - - current_date]]> - - 100]]> - - 10000]]> - - - Las funciones SQL any, some, all, exists, in están soportadas cuando se les pasa - el conjunto de elementos o índices de una colección (funciones elements y - indices) o el resultado de una subconsulta (ver debajo). - - - - - - - - - all elements(p.scores)]]> - - - - - Nota que estas construcciones - size, elements, - indices, minindex, maxindex, - minelement, maxelement - pueden ser usadas solamente - en la cláusula where en Hibernate3. - - - - Los elementos de colecciones indexadas (arrays, listas, mapas) pueden ser referidos por índice - (en una cláusula where solamente): - - - - - - - - - - - - La expresión dentro de [] puede incluso ser una expresión aritmética. - - - - - - HQL provee además el función prefabricada index(), para elementos de una - asociación uno-a-muchos o colección de valores. - - - - - - Pueden usarse las funciones SQL escalares soportadas por la base de datos subyacente - - - - - - Si aún no estás convencido de todo esto, piensa cuánto más largo y menos leíble sería la siguiente - consulta en SQL: - - - - - - Ayuda: algo como - - - - - - - - La cláusula order by - - - La lista devuelta por una consulta puede ser ordenada por cualquier propiedad de una clase devuelta - o componentes: - - - - - - Los asc o desc opcionales indican ordenamiento ascendente o - descendente respectivamente. - - - - - La cláusula group by - - - Una consulta que devuelve valores agregados puede ser agrupada por cualquier propiedad de una clase - devuelta o componentes: - - - - - - - - Se permite también una cláusula having. - - - - - - Las funciones y funciones de agregación SQL están permitidas en las cláusulas - having y order by, si están soportadas por la base de datos - subyacente (por ejemplo, no en MySQL). - - - 100 -order by count(kitten) asc, sum(kitten.weight) desc]]> - - - Nota que ni la cláusula group by ni la cláusula order by pueden - contener expresiones aritméticas. - - - - - - Subconsultas - - - Para bases de datos que soportan subconsultas, Hibernate soporta subconsultas dentro de consultas. Una - subconsulta debe ser encerrada entre paréntesis (frecuentemente por una llamada a una función de agregación - SQL). Incluso se permiten subconsultas correlacionadas (subconsultas que hacen referencia a un alias en la - consulta exterior). - - - ( - select avg(cat.weight) from DomesticCat cat -)]]> - - - - - - - - - Para las subconsultas con más de una expresión en la lista de selección, puedes usar un constructor - de tuplas: - - - - - - Nota que en algunas bases de datos (pero no en Oracle o HSQL), puedes usar constructores de tuplar en - otros contextos, por ejemplo al consultar componentes o tipos de usuario compuestos: - - - - - - Que es equivalente a la más verborrágica: - - - - - - Existen dos buenas razones por las cuales podrías no querer hacer este tipo de cosa: primero, no es - completamente portable entre plataformas de base de datos; segundo, la consulta ahora es dependiente - del orden de propiedades en el documento de mapeo. - - - - - - Ejemplos de HQL - - - Las consultas de Hibernate pueden ser abolutamente potentes y complejas, De hecho, el poder del lenguaje - de consulta es uno de los puntos principales de venta de Hibernate. He aquí algunos consultas de ejemplo - muy similares a consultas que he usado en un proyecto reciente. ¡Nota que la mayoría de las consultas - que escribirás som mucho más simples que estas! - - - - La siguiente consulta devuelve el order id, número de items y valor total de la orden para todas - las ordenes inpagas de un cliente en particular y valor total mínimo dados, ordenando los resultados - por valor total. Al determinar los precios, usa el catálogo actual. La consulta SQL resultante, - contra las tablas ORDER, ORDER_LINE, PRODUCT, - CATALOG and PRICE tiene cuatro joins interiores y una subselect - (no correlacionada). - - - = all ( - select cat.effectiveDate - from Catalog as cat - where cat.effectiveDate < sysdate - ) -group by order -having sum(price.amount) > :minAmount -order by sum(price.amount) desc]]> - - - ¡Qué monstruo! Realmente, en la vida real, no estoy muy afilado en subconsultas, de modo que mi - consulta fue realmente algo como esto: - - - :minAmount -order by sum(price.amount) desc]]> - - - La próxima consulta cuenta el número de pagos en cada estado, excluyendo todos los pagos - en el estado AWAITING_APPROVAL donde el estado más reciente fue hecho por el - usuario actual. Se traduce en una consulta SQL con dos joins interiores y una subselect - correlacionada contra las tablas PAYMENT, PAYMENT_STATUS y - PAYMENT_STATUS_CHANGE. - - - PaymentStatus.AWAITING_APPROVAL - or ( - statusChange.timeStamp = ( - select max(change.timeStamp) - from PaymentStatusChange change - where change.payment = payment - ) - and statusChange.user <> :currentUser - ) -group by status.name, status.sortOrder -order by status.sortOrder]]> - - - Si hubiese mapeado la colección statusChanges como una lista, en vez de un conjunto, - la consulta habría sido mucho más simple de escribir. - - - PaymentStatus.AWAITING_APPROVAL - or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser -group by status.name, status.sortOrder -order by status.sortOrder]]> - - - La próxima consulta usa la función isNull() de MS SQL Server para devolver - todas las cuentas y pagos inpagos de la organización a la que pertenece el usuario actual. - Se traduce en una consulta SQL con tres joins interiores, un join exterior y una subconsulta - contra las tablas ACCOUNT, PAYMENT, PAYMENT_STATUS, - ACCOUNT_TYPE, ORGANIZATION y ORG_USER. - - - - - - Para algunas bases de datos, necesitaríamos eliminar la subselect (correlacionada). - - - - - - - - Sentencias UPDATE y DELETE masivas - - - HQL soporta ahora sentencias UPDATE y DELETE en HQL. - Ver para detalles. - - - - - Consejos y Trucos - - - Puedes contar el número de resultados de una consulta sin devolverlos realmente: - - - - - - Para ordenar un resultado por el tamaño de una colección, usa la siguiente consulta: - - - - - - Si tu base de datos soporta subselects, puedes colocar una condición sobre el tamaño de selección - en la cláusula where de tu consulta: - - - = 1]]> - - - Si tu base de datos no soporta subselects, usa la siguiente consulta: - - - = 1]]> - - - Como esta solución no puede devolver un User con cero mensajes debido a la unión interior, - la siguiente forma es también útil: - - - - - - Las propiedades de un JavaBean pueden ser ligadas al parámetros de consulta con nombre: - - - - - - Las colecciones son paginables usando la interface Query con un filtro: - - - - - - Los elementos de colección pueden ser ordenados o agrupados usando un filtro de consulta: - - - - - - Puedes hallar el tamaño de una colección sin inicializarla: - - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/query_sql.xml b/documentation/manual/es-ES/src/main/docbook/modules/query_sql.xml deleted file mode 100644 index 5bfebad7cd..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/query_sql.xml +++ /dev/null @@ -1,477 +0,0 @@ - - SQL Nativo - - - Puedes también expresar consultas en el dialecto SQL nativo de tu base de datos. Esto es útil si quieres - utilizar aspectos específicos de base de datos tal como consejos (hints) de consulta o la palabra clave - CONNECT en Oracle. Provee además una clara ruta de migración desde una aplicación - basada en SQL/JDBC directo a Hibernate. - - - - Hibernate3 te permite especificar SQL escrito a mano (incluyendo procedimientos almacenados) para todas - las operaciones de creación, actualización, borrado y carga. - - - - Creando una <literal>Query</literal> de SQL nativo - - - Las consultas SQL se controlan por medio de la interface SQLQuery, que se obtiene - llamando a Session.createSQLQuery(). - - - - - - Esta consulta especificada: - - - - - - la cadena de consulta SQL, con un lugar para que Hibernate inyecte los alias de columnas - - - - - la entidad devuelta por la consulta, y sus alias de tablas SQL - - - - - - El método addEntity() asocia alias de tablas SQL con clases de entidad, - y determina la forma del conjunto resultado de la consulta. - - - - El método addJoin() puede ser usado para cargar asociaciones a otras entidades y - colecciones. - - - - - - Una consulta SQL nativa podría devolver un valor escalar simple o una combinación de escalares y entidades. - - - - - - - - - Alias y referencias de propiedad - - - La notación {cat.*} usada arriba es un atajo para "todas las propiedades". - Alternativamente, puedes listar las columnas explícitamente, pero incluso en este caso dejamos - que Hibernate inyecte los alias de columnas SQL para cada propiedad. El lugar para un alias de columna - es sólo el nombre de propiedad cualificado por el alias de la tabla. En el siguiente ejemplo, - recuperamos Cats de una tabla diferente (cat_log) a una - declarada en los metadatos de mapeo. Nota que podríamos incluso usar los alias de propiedad en la - cláusula where si quisieramos. - - - La sintáxis {} no es requerida para consultas con nombre. - Ver - - - - - - Nota: si listas cada propiedad explícitamente, ¡debes incluir todas las - propiedades de la clase y sus subclases! - - - - - - Consultas SQL con nombre - - - Las consultas SQL con nombre pueden definirse en el documento de mapeo y llamadas exactamente - en la misma forma en que a una consulta HQL con nombre. En este caso, no - necesitamos llamar a addEntity(). - - - - - SELECT person.NAME AS {person.name}, - person.AGE AS {person.age}, - person.SEX AS {person.sex} - FROM PERSON person - WHERE person.NAME LIKE :namePattern -]]> - - - - - Los elementos <return-join> y <load-collection> - se usan para unir asociaciones y definir consultas que inicialicen colecciones, respectivamente. - - - - - - SELECT person.NAME AS {person.name}, - person.AGE AS {person.age}, - person.SEX AS {person.sex}, - address.STREET AS {address.street}, - address.CITY AS {address.city}, - address.STATE AS {address.state}, - address.ZIP AS {address.zip} - FROM PERSON person - JOIN ADDRESS address - ON person.ID = address.PERSON_ID AND address.TYPE='MAILING' - WHERE person.NAME LIKE :namePattern -]]> - - - Una consulta SQL con nombre puede devolver un valor escalar. Debes especificar el alias de columna y - tipo Hibernate usando el elementp <return-scalar>: - - - - - - SELECT p.NAME AS name, - p.AGE AS age, - FROM PERSON p WHERE p.NAME LIKE 'Hiber%' -]]> - - - Usando return-property para especificar explícitamente nombres de columna/alias - - - Con <return-property> puedes decirle explícitamente a Hibernate qué - alias de columna usar, en vez de usar la sintáxis {} para dejar que Hibernate - inyecte sus propios alias. - - - - - - - - - SELECT person.NAME AS myName, - person.AGE AS myAge, - person.SEX AS mySex, - FROM PERSON person WHERE person.NAME LIKE :name - -]]> - - - <return-property> también trabaja con múltiples columnas. Esto resuelve una - limitación de la sintáxis {}, la cual no puede permitir un control fino de propiedades - multi-columna. - - - - - - - - - - - SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer}, - STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate}, - REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY - FROM EMPLOYMENT - WHERE EMPLOYER = :id AND ENDDATE IS NULL - ORDER BY STARTDATE ASC -]]> - - - Nota que en este ejemplo hemos usado <return-property> en combinación con - la sintáxis {} para inyección, permitiendo a los usuarios elejir cómo quieren - referirse a las columnas y propiedades. - - - - Si tu mapeo tiene un discriminador debes usar <return-discriminator> - para especificar la columna discriminadora. - - - - - Usando procedimientos almacenados para consultar - - - Hibernate3 introduce soporte para consultas vía procedimientos almacenados. Los procedimientos - almacenados deben devolver un conjunto resultado como el primer parámetro de salida para ser - capaces de funcionar con Hibernate. Un ejemplo de uno procedimiento almacenado en Oracle 9 - o superior es así: - - - - - - Para usar esta consulta en Hibernate necesitas mapearla por medio de una consulta con nombre. - - - - - - - - - - - - - - - - { ? = call selectAllEmployments() } -]]> - - - Nota que los procedimientos almacenados sólo devuelven escalares y entidades. - No están soportados <return-join> y <load-collection>. - - - - Reglas/limitaciones para usar procedimientos almacenados - - - Para usar procedimientos almacenados con Hibernate los procedimientos tienen que seguir algunas reglas. - Si no siguen esas reglas no son usables por Hibernate. Si aún quisieras usar estos procedimientos - tendrías que ejecutarlos por medio de session.connection(). Las reglas son - diferentes para cada base de datos, ya que los vendedores de base de datos tienen diferentes - semánticas/sintáxis de procedimientos almacenados. - - - - Las consultas de procedimientos almacenados no pueden ser paginadas con - setFirstResult()/setMaxResults(). - - - - Para Oracle se aplican las siguientes reglas: - - - - - - El procedimiento debe devolver un conjunto resultado. Esto se hace devolviendo un - SYS_REFCURSOR en Oracle 9 o 10. En Oracle necesitas definir un - tipo REF CURSOR. - - - - - La forma recomendada es { ? = call procName(<parameters>) } o - { ? = call procName } (esto es más una regla de Oracle que una regla de Hibernate). - - - - - - Para Sybase o MS SQL server se aplican las siguientes reglas: - - - - - - El procedimiento debe devolver un conjunto resultado. Nota que ya que estos servidores pueden - y devolverán múltiples conjuntos resultados y cuentas de actualización, Hibernate iterará - los resultados y tomará el primer resultado que sea un conjunto resultado como su valor - a devolver. Todo lo demás será descartado. - - - - - Si habilitas SET NOCOUNT ON en tu procedimiento será probablemente más - eficiente, pero esto no es un requerimiento. - - - - - - - - - - SQL personalizado para crear, actualizar y borrar - - - Hibernate3 puede usar sentencias SQL personalizadas para las operaciones de - crear, actualizar y borrar. Los persistidores de clases y colecciones en Hibernate - ya contienen un conjunto de cadenas generadas en tiempo de configuración (insertsql, - deletesql, updatesql, etc.). Las etiquetas de mapeo <sql-insert>, - <sql-delete>, y <sql-update> sobrescriben - estas cadenas: - - - - - - - - INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? ) - UPDATE PERSON SET NAME=UPPER(?) WHERE ID=? - DELETE FROM PERSON WHERE ID=? -]]> - - - El SQL se ejecuta directamente en tu base de datos, de modo que eres libre de usar cualquier - dialecto que quieras. Esto reducirá, por supuesto, la portabilidad de tu mapeo si usas SQL - específico de la base de datos. - - - - Los procedimientos almacenados son soportados si está establecido el atributo - callable: - - - - - - - - {call createPerson (?, ?)} - {? = call deletePerson (?)} - {? = call updatePerson (?, ?)} -]]> - - - El orden de los parámetros posicionales son actualmente vitales, ya que deben estar en la - misma secuencia en que las espera Hibernate. - - - - Puedes ver el orden esperado habilitando el registro de depuración para el nivel - org.hibernate.persister.entity. Con este nivel habilitado, Hibernate - imprimirá el SQL estático que se usa para crear, actualizar, borrar, etc. las entidades. - (Para ver la secuencia esperada, recuerda no incluir tu SQL personalizado en los ficheros - de mapeo ya que sobrescribirán el sql estático generado por Hibernate.) - - - - Los procedimientos almacenados son, en la mayoría de los casos (léase, mejor hacerlo que no hacerlo), - obligados a devolver el número de filas insertadas/actualizadas/borradas, ya que Hibernate tiene algunas - comprobaciones en tiempo de ejecución del éxito de la sentencia. Hibernate siempre registra el primer - parámetro de la sentencia como un parámetro de salida numérico para las operaciones CUD: - - - - - - - - - SQL personalizado para carga - - - Puedes también declarar tu propias consultas SQL (o HQL) para cargar entidades: - - - - - SELECT NAME AS {pers.name}, ID AS {pers.id} - FROM PERSON - WHERE ID=? - FOR UPDATE -]]> - - - Esto es sólo una declaración de consulta con nombrem como se ha discutido anteriormente. - Puedes hacer referencia a esta consulta con nombre en un mapeo de clase: - - - - - - - - -]]> - - - Esto incluso funciona con procedimientos almacenados. - - - - Puedes incluso definit una consulta para la carga de colecciones: - - - - - - -]]> - - - - SELECT {emp.*} - FROM EMPLOYMENT emp - WHERE EMPLOYER = :id - ORDER BY STARTDATE ASC, EMPLOYEE ASC -]]> - - - Podrías incluso definir un cargador de entidades que cargue una colección por - recuperación por unión (join fetching): - - - - - - SELECT NAME AS {pers.*}, {emp.*} - FROM PERSON pers - LEFT OUTER JOIN EMPLOYMENT emp - ON pers.ID = emp.PERSON_ID - WHERE ID=? -]]> - - - - \ No newline at end of file diff --git a/documentation/manual/es-ES/src/main/docbook/modules/quickstart.xml b/documentation/manual/es-ES/src/main/docbook/modules/quickstart.xml deleted file mode 100644 index a526c45b17..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/quickstart.xml +++ /dev/null @@ -1,666 +0,0 @@ - - Comienzo rápido con Tomcat - - - Empezando con Hibernate - - - Este tutorial explica una instalación de Hibernate con el - contenedor de servlets Apache Tomcat (hemos usado la versión 4.1, - las diferencias con la 5.0 deben ser mínimas) para una aplicación - basada en web. Hibernate trabaja bien en un entorno manejado con - todos los servidores de aplicaciones J2EE importantes, o incluso en aplicaciones - Java independientes. El sistema de base de datos es sólo una cuestión - de cambiar la configuración del dialecto SQL de Hibernate y las - propiedades de conexión. - - - - Primero, tenemos que copiar todas las bibliotecas requeridas a la instalación - de Tomcat. Usamos un contexto web separado (webapps/quickstart) - para este tutorial, de modo que tenemos que considerar tanto la ruta de búsqueda - de bibliotecas global (TOMCAT/common/lib) como también - el cargador de clases a nivel de contexto en webapps/quickstart/WEB-INF/lib - (para ficheros JAR) y webapps/quickstart/WEB-INF/classes. - Nos referiremos a ambos niveles de cargador de clases como el classpath global y el classpath - de contexto, respectivamente. - - - - Ahora, copia las bibliotecas a los dos classpaths: - - - - - - Copia el driver JDBC para la base de datos al classpath global. Esto se - requiere para el software de pool de conexiones DBCP que se distribuye - con Tomcat. Hibernate usa conexiones JDBC para ejecutar SQL sobre la base de - datos, de modo que, o bien tienes que proveer conexiones JDBC en pool, - o bien configurar Hibernate para que use uno de los pools soportados - directamente (C3P0, Proxool). Para este tutorial, copia la biblioteca - pg74jdbc3.jar (para PostgreSQL 7.4 y JDK 1.4) al - classpath del cargador global. Si quisieras usar una base de datos diferente, - simplemente copia su apropiado driver JDBC. - - - - - Nunca copies nada más dentro de la ruta del cargador de clases global - en Tomcat, o tendrás problemas con varias herramientas, incluyendo - Log4J, commons-logging y otras. Siempre usa el classpath de contexto para - cada aplicación web, esto es, copia las bibliotecas a - WEB-INF/lib y tus propias clases y ficheros de - configuración/propiedades a WEB-INF/classes. - Ambos directorios están a nivel del classpath de contexto por defecto. - - - - - Hibernate está empaquetado como una biblioteca JAR. El fichero - hibernate3.jar debe ser copiado en el classpath de contexto - junto a las otras clases de la aplicación. Hibernate requiere algunas - bibliotecas de terceros en tiempo de ejecución; éstas vienen - incluídas con la distribución de Hibernate en el directorio - lib/. Ver . Copia las - bibliotecas de terceros requeridas al classpath de contexto. - - - - - - - Bibliotecas de terceros de Hibernate - - - - - - - - Biblioteca - - - Descripción - - - - - - - antlr (requerida) - - - Hibernate usa ANTLR para producir analizadores de consultas, - esta biblioteca también se necesita en tiempo de ejecución. - - - - - dom4j (requerida) - - - Hibernate usa dom4j para analizar ficheros de configuración - XML y ficheros de metadatos de mapeo XML. - - - - - CGLIB, asm (requerida) - - - Hibernate usa la biblioteca de generación de código - para aumentar las clases en tiempo de ejecución - (en combinación con reflección Java). - - - - - Commons Collections, Commons Logging (requeridas) - - - Hibernate usa varias bibliotecas de utilidad del proyecto - Jakarta Commons de Apache. - - - - - EHCache (requerida) - - - Hibernate puede usar varios provedores de caché para - el caché de segundo nivel. EHCache es el provedor de - caché por defecto si no se cambia en la configuración. - - - - - Log4j (opcional) - - - Hibernate usa la API de Commons Logging, que a su vez puede - usar Log4J como el mecanismo de logging subyacente. Si la - biblioteca Log4J está disponible en el directorio de - bibliotecas del contexto, Commons Logging usará Log4J - y la configuración log4j.properties - en el classpath de contexto. Un fichero de propiedades de ejemplo - para Log4J se incluye con la distribución de Hibernate. - Así que copia log4j.jar y el fichero de configuración - (de src/) a tu classpath de contexto si quieres - ver que ocurre tras escénas. - - - - - ¿Requerida o no? - - - Echa una mirada al fichero lib/README.txt en la - distribución de Hibernate. Esta es una lista actualizada - de bibliotecas de terceros distribuídas con Hibernate. - Encontrarás listadas ahí todas las bibliotecas - requeridas y opcionales (Observa que "buildtame required" significa - aquí para la construcción de Hibernate, no de tu - aplicación). - - - - -
- - - Ahora instalamos el pooling y modo compartido de conexiones de base de datos - tanto en Tomcat como Hibernate. Esto significa que Tomcat proveerá - conexiones JDBC en pool (usando su funcionalidad prefabricada de pooling DBCP). - Hibernate pide esas conexiones a través de JNDI. Alternativamente, - puedes dejar que Hibernate maneje el pool de conexiones. Tomcat liga su pool - de conexiones a JNDI; agregamos una declaración de recurso al fichero - de configuración principal de Tomcat, TOMCAT/conf/server.xml: - - - - - - - factory - org.apache.commons.dbcp.BasicDataSourceFactory - - - - - url - jdbc:postgresql://localhost/quickstart - - - driverClassNameorg.postgresql.Driver - - - username - quickstart - - - password - secret - - - - - maxWait - 3000 - - - maxIdle - 100 - - - maxActive - 10 - - -]]> - - - El contexto que configuramos en este ejemplo se llama quickstart, - su base es el directorio TOMCAT/webapp/quickstart. Para acceder - a cualquier servlet, llama a la ruta http://localhost:8080/quickstart - en tu navegador (por supuesto, agregando el nombre del servlet como se mapee en tu - web.xml). Puedes también ir más allá y crear - ahora un servlet simple que tenga un método process() - vacío. - - - - Tomcat provee ahora conexiones a través de JNDI en - java:comp/env/jdbc/quickstart. Si tienes problemas obteniendo - el pool de conexiones en ejecución, refiérete a la documentación - de Tomcat. Si obtienes mensajes de excepción del driver JDBC, intenta instalar - primero el pool de conexiones JDBC sin Hibernate. Hay disponibles en la Web - tutoriales de Tomcat y JDBC. - - - - Tu próximo paso es configurar Hibernate. Hibernate tiene que saber cómo - debe obtener conexiones JDBC. Usamos la configuración de Hibernate basada en XML. - El otro enfoque, usando un ficheros de propiedad, es casi equivalente pero pierde unas - pocas funcionalidades que sí permite la sintaxis XML. El fichero de configuración - XML se ubica en el classpath de contexto (WEB-INF/classes), como - hibernate.cfg.xml: - - - - - - - - - - java:comp/env/jdbc/quickstart - false - org.hibernate.dialect.PostgreSQLDialect - - - - - - -]]> - - - Desactivamos el registro (logging) de comandos SQL y decimos a Hibernate - qué dialecto SQL de base de datos se usa y dónde obtener - conexiones JDBC (declarando la dirección JNDI del pool ligado a - Tomcat). El dialecto es una configuración requerida, las bases de - datos difieren en su interpretación del "estándar" de SQL. - Hibernate cuidará de las diferencias y viene con dialectos incluídos - para todas las principales bases de datos comerciales y de código - abierto. - - - - Una SessionFactory es el concepto de Hibernate - de un almacén de datos solo. Pueden usarse múltiples - bases de datos creando múltiples ficheros de configuración - XML y creando múltiples objetos Configuration - y SessionFactory en tu aplicación. - - - - El último elemento del hibernate.cfg.xml - declara Cat.hbm.xml como el nombre de un fichero - de mapeo XML para la clase persistente Cat. Este - fichero contiene los metadatos para el mapeo de la clase POJO - Cat a una tabla (o tablas) de base de datos. - Volveremos a este fichero pronto. Escribamos primero la clase POJO - y luego declaremos los metadatos de mapeo para ella. - - -
- - - Primera clase persistente - - - Hibernate trabaja mejor con el modelo de programación de los - Viejos Objetos Planos de Java (POJOs, a veces llamados Ordinarios Objetos Planos de Java) - para clases persistentes. Un POJO es como un JavaBean, con las propiedades - de la clase accesible vía métodos getter y setter, - encapsulando la representación interna de la interfaz publicamente - visible (Hibernate puede también acceder a los campos directamente, si se - necesita): - - - - - - Hibernate no está restringido en su uso de tipos de propiedad, todos - los tipos y tipos primitivos del JDK de Java (como String, - char y Date) pueden ser mapeados, incluyendo - clases del framework de colecciones de Java. Puedes mapearlos como valores, - colecciones de valores, o asociaciones a otras entidades. El id - es una propiedad especial que representa el identificador de base de datos (clave - primaria) de la clase. Es altamente recomendado para entidades como un - Cat. Hibernate puede usar identificadores sólo - internamente, pero perderíamos algo de la flexibilidad en nuestra - arquitectura de aplicación. - - - - No tiene que implementarse ninguna interface especial para las clases persistentes - ni tienes que subclasear de una clase persistente raíz en especial. Hibernate - tampoco requiere ningún procesamiento en tiempo de construcción, - como manipulación del byte-code. Se basa solamente en reflección de Java - y aumentación de clases en tiempo de ejecución (a través de CGLIB). - De modo que, sin ninguna dependencia de la clase POJO en Hibernate, podemos mapearla - a una tabla de base de datos. - - - - - - Mapeando el gato - - - El fichero de mapeo Cat.hbm.xml contiene los - metadatos requeridos para el mapeo objeto/relacional. Los metadatos - incluyen la declaración de clases persistentes y el mapeo de - propiedades (a columnas y relaciones de claves foráneas a otras - entidades) a tablas de base de datos. - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Cada clase persistente debe tener un atributo identificador (realmente, - sólo las clases que representen entidades, no las clases dependientes - de tipo-valor, que son mapeadas como componentes de una entidad). Esta propiedad - es usada para distinguir los objetos persistentes: Dos gatos son iguales si - catA.getId().equals(catB.getId()) es verdadero. Este concepto - se llama identidad de base de datos (database identity). - Hibernate viene empaquetado con varios generadores de identificador para diferentes - escenarios (incluyendo generadores nativos para secuencias de base de datos, tablas - de identificadores alto/bajo, e identificadores asignados por aplicación). - Usamos el generador UUID (recomendado sólo para pruebas, pues deben - preferirse las claves enteras delegadas generadas por la base de datos) y - también especificamos la columna CAT_ID de la tabla - CAT para el valor identificador generado por Hibernate - (como una clave primaria de la tabla). - - - - Todas las demás propiedades de Cat son mapeadas a la - misma tabla. En el caso de la propiedad name, la hemos mapeado - con una declaración explícita de columna de base de datos. Esto es - especialmente útil cuando el esquema de base de datos es generado - automáticamente (como sentencias DDL de SQL) desde la declaración - de mapeo con la herramienta SchemaExport de Hibernate. - Todas las demás propiedades son mapeadas usando la configuración - por defecto de Hibernate, que es lo que necesitas la mayoría del tiempo. - La tabla CAT en la base de datos se ve así como: - - - - - - Ahora debes crear esta tabla manualmente en tu base de datos, y luego leer el - si quieres automatizar este paso con la - herramienta hbm2ddl. Esta herramienta puede crear un - DDL SQL completo, incluyendo definición de tablas, restricciones - personalizadas de tipo de columnas, restricciones de unicidad e índices. - - - - - - Jugando con gatos - - - Ahora estamos listos para comenzar la Session de Hibernate. - Es el manejador de persistencia que usamos para almacenar - y traer Cats hacia y desde la base de datos. Pero primero, - tenemos que obtener una Session (unidad de trabajo de Hibernate) - de la SessionFactory: - - - - - - La llamada a configure() carga el fichero de - configuración hibernate.cfg.xml e - inicializa la instancia de Configuration. - Puedes establecer otras propiedades (e incluso cambiar los metadatos de mapeo) - accediendo a la Configuration antes - que construyas la SessionFactory (que es inmutable). - ¿Dónde creamos la SessionFactory y cómo - accedemos a ella en nuestra aplicación? - - - - Una SessionFactory usualmente se construye una vez, - por ejemplo, al arrancar con un servlet load-on-startup. - Esto significa también que no debes mantenerla en una variable de instancia - en tus servlets, sino en alguna otro sitio. Además, necesitamos algún - tipo de Singleton, de modo que podamos acceder a la - SessionFactory fácilmente en el código de - aplicación. El siguiente enfoque mostrado resuelve ambos problemas: - configuración de arranque y fácil acceso a una - SessionFactory. - - - - Implementamos una clase de ayuda HibernateUtil: - - - - - - Esta clase no sólo cuida de la SessionFactory - con su inicializador static, sino que además tiene una variable - ThreadLocal que tiene la Session - para la hebra actual. Asegúrate de entender el concepto Java de una - variable local a una hebra antes de intentar usar esta ayuda. Una clase - HibernateUtil más compleja y potente puede - encontrarse en CaveatEmptor, http://caveatemptor.hibernate.org/ - - - - Una SessionFactory es segura entre hebras, muchas hebras pueden - acceder a ella concurrentemente y pedirle Sessions. Una - Session no es un objeto seguro entre hebras que representa - una sola unidad-de-trabajo con la base de datos. Las Sessions - se abren desde una SessionFactory y son cerradas cuando - todo el trabajo está completo. Un ejemplo en el método - process() de tu servlet podría parecerse a esto - (sin manejo de excepciones): - - - - - - En una Session, cada operación de base de datos - ocurre dentro de una transacción que aísla las operaciones - de base de datos (incluso operaciones de sólo lectura). - Usamos la API de Transaction de Hibernate para - abstraer de la estrategia de transacciones subyacente (en nuestro caso, - transacciones JDBC). Esto permite que nuestro código sea desplegado - con transacciones manejadas por contenedor (usando JTA) sin cambio alguno. - - - - Observa que puedes llamar HibernateUtil.currentSession(); - tantas veces como quieras, siempre obtendrás la Session - actual de esta hebra. Tienes que asegurarte que la Session - sea cerrada después que se complete tu unidad-de-trabajo, ya sea en - código de tu servlet o en un filtro de servlet antes que la respuesta HTTP - sea enviada. El bonito efecto colateral de la segunda opción es la - fácil inicialización perezosa: la Session todavía - está abierta cuando se dibuja la vista, de modo que Hibernate puede cargar - objetos no inicializados mientras navegas tu actual grafo de objetos. - - - - Hibernate tiene varios métodos que pueden ser usados para traer - objetos desde la base de datos. La forma más flexible es usando - el Lenguaje de Consulta de Hibernate (Hibernate Query Language o HQL), - que es una extensión orientada a objetos de SQL fácil de - aprender: - - - - - - Hibernate también ofrece una API consulta por criterios - orientada a objetos que puede ser usada para formular consultas de tipo seguro. - Por supuesto, Hibernate usa PreparedStatements y ligado de - parámetros para toda la comunicación SQL con la base de datos. - También puedes usar la funcionalidad de consulta SQL directa de Hibernate - u obtener una conexión plana de JDBC de una Session - en casos raros. - - - - - - Finalmente - - - Rasguñamos solamente la superficie de Hibernate en este pequeño - tutorial. Por favor, observa que no incluimos ningún código - específico de servlet en nuestros ejemplos. Tienes que crear un servlet - por tí mismo e insertar el código de Hibernate como lo veas - ubicado. - - - - Ten en mente que Hibernate, como capa de acceso a datos, está firmemente - integrado dentro de tu aplicación. Usualmente, todas las otras capas dependen - del mecanismo de persistencia. Asegúrate de entender las implicaciones - de este diseño. - - - - Para un ejemplo de aplicación más compleja, ver - http://caveatemptor.hibernate.org/ y echa una mirada a los - otros tutoriales con links en http://www.hibernate.org/Documentation - - - - -
diff --git a/documentation/manual/es-ES/src/main/docbook/modules/session_api.xml b/documentation/manual/es-ES/src/main/docbook/modules/session_api.xml deleted file mode 100644 index c8d23f2e87..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/session_api.xml +++ /dev/null @@ -1,1224 +0,0 @@ - - Trabajando con objetos - - - Hibernate es una solución completa de mapeo objeto/relacional que no sólo - abstrae al desarrollador de los detalles del sistema de manejo de base datos - subyacente, sino que además ofrece manejo de estado de - objetos. Esto es, al contrario del manejo de sentencias - SQL en capas comunes de persistencia JDBC/SQL, una vista de la persistencia - en aplicaciones Java muy natural y orientada a objetos. - - - - En otras palabras, los desarroladores de aplicaciones Hibernate deben siempre - pensar en el estado de sus objetos, y no necesariamente - en la ejecución de sentencias SQL. Esta parte es cuidada por Hibernate y es - sólo relevante para el desarrollador de la aplicación al afinar el rendimiento - del sistema. - - - - Estados de objeto de Hibernate - - - Hibernate define y soporta los siguientes estados de objeto: - - - - - - Transitorio - un objeto es transitorio si ha sido - recién instanciado usando el operador new, y no está - asociado a una Session de Hibernate. No tiene una - representación persistente en la base de datos y no se le ha asignado un - valor identificador. Las instancias transitorias serán destruídas por el - recolector de basura si la aplicación no mantiene más una referencia. - Usa la Session de Hibernate para hacer un objeto - persistente (y deja que Hibernate cuide de las sentencias SQL que necesitan - ejecutarse para esta transición). - - - - - Persistente - una instancia persistente tiene una - representación en la base de datos y un valor identificador. Puede haber - sido salvado o cargado, sin embargo, está por definición en el ámbito de - una Session. Hibernate detectará cualquier cambio hecho - a un objeto en estado persistentey sincronizará el estado con la base de - datos cuando se complete la unidad de trabajo. Los desarrolladores no ejecutan - sentencias UPDATE manuales, o sentencias DELETE - cuando un objeto debe ser hecho transitorio. - - - - - Separado (detached) - una instancia separada es un objeto - que ha sido hecho persistente, pero su Session ha sido cerrada. - La referencia al objeto todavía es válida, por supuesto, y la instancia separada - podría incluso ser modificada en este estado. Una instancia separada puede ser - re-unida a una nueva Session en un punto posterior en el tiempo, - haciéndola persistente de nuevo (con todas las modificaciones). Este aspecto - habilita un modelo de programación para unidades de trabajo de ejecución larga - que requieren tiempo-para-pensar del usuario. Las llamamos transaccciones - de aplicación, es decir, una unidad de trabajo desde el punto de vista - del usuario. - - - - - - Discutiremos ahora los estados y transiciones de estados (y los métodos de Hibernate que - disparan una transición) en más detalle: - - - - - - Haciendo los objetos persistentes - - - Las instancias recién instanciadas de una clase persistente son consideradas - transitorias por Hibernate. Podemos hacer una instancia - transitoria persistente asociándola con una sesión: - - - - - - Si Cat tiene un identificador generado, el identificador es - generado y asignado al cat cuando se llama a save(). - Si Cat tiene un identificador assigned, - o una clave compuesta, el identificador debe ser asignado a la instancia de - cat antes de llamar a save(). Puedes también - usar persist() en vez de save(), con la semántica - definida en el temprano borrador de EJB3. - - - - Alternativamente, puedes asignar el identificador usando una versión sobrecargada - de save(). - - - - - - Si el objeto que haces persistente tiene objetos asociados (por ejemplo, - la colección kittens en el ejemplo anterior), estos - objetos pueden ser hechos persistentes en cualquier orden que quieras - a menos que tengas una restricción NOT NULL sobre una - columna clave foránea. Nunca hay riesgo de violar restricciones de clave - foránea. Sin embargo, podrías violar una restricción NOT NULL - si llamas a save() sobre objetos en orden erróneo. - - - - Usualmente no te preocupas con este detalle, pues muy probablemente usarás - la funcionalidad de persistencia transitiva de Hibernate - para salvar los objetos asociados automáticamente. Entonces, ni siquiera ocurren - violaciones de restricciones NOT NULL - Hibernate cuidará de todo. - La persistencia transitiva se discute más adelante en este capítulo. - - - - - - Cargando un objeto - - - Los métodos load() de Session te brindan - una forma de traer una instancia persistente si ya saves su identificador. - load() toma un objeto clase y cargará el estado dentro de - una instancia recién instanciada de esta clase, en estado persistente. - - - - - - - - Alternativamente, puedes cargar estado dentro de una instancia dada: - - - - - - Nota que load() lanzará una excepción irrecuperable si no - hay una fila correspondiente en base de datos. Si la clase es mapeada con un - proxy, load() sólo devuelve un proxy no inicializado y no - llamará realmente a la base de datos hasta que invoques un método del proxy. - Este comportamiento es muy útil si deseas crear una asociación a un objeto - sin cargarlo realmente de la base de datos. Permite además que múltiples - instancias sean cargadas como un lote si se define batch-size - para el mapeo de la clase. - - - - Si no tienes certeza que exista una fila correspondiente, debes usar el - método get(), que llama a la base de datos inmediatamente - y devuelve nulo si no existe una fila correspondiente. - - - - - - Puedes incluso cargar un objeto usando un SELECT ... FOR UPDATE de SQL, - usando un LockMode. Ver la documentación de la API para más - información. - - - - - - Ten en cuenta que ninguna instancia asociada o colección contenida es - selecciona FOR UPDATE, a menos que decidas especificar - lock o all como un estilo de cascada para la - asociación. - - - - Es posible volver a cargar un objeto y todas sus colecciones en cualquier momento, - usando el método refresh(). Esto es útil cuando se usan disparadores de - base de datos para inicializar algunas de las propiedades del objeto. - - - - - - Una cuestión importante aparece usualmente en este punto: ¿Cuánto carga Hibernate de - la base de datos y cuántos SELECTs de SQL usará? Esto depende de la - estrategia de recuperación y se explica en . - - - - - - Consultando - - - Si no sabes los identificadores de los objetos que estás buscando, - necesitas una consulta. Hibernate soporta un lenguaje de consulta - orientado a objetos (HQL) fácil de usar pero potente. Para la creación - de consultas programáticas, Hibernate soporta una funcionalidad sofisticada - de consulta de Criteria y Example (QBC and QBE). También puedes expresar tu - consulta en el SQL nativo de tu base de datos, con soporte opcional de Hibernate - para la conversión del conjunto resultado en objetos. - - - - Ejecutando consultas - - - Las consultas HQL y SQL nativas son representadas con una instancia de - org.hibernate.Query. Esta interface ofrece métodos para - la ligación de parámetros, manejo del conjunto resultado, y para la - ejecución de la consulta real. Siempre obtienes una Query - usando la Session actual: - - - - - - Una consulta se ejecuta usualmente invocando a list(), - el resultado de la consulta será cargado completamente dentro de una - colección en memoria. Las instancias de entidad traídas por una consulta - están en estado persistente. El método uniqueResult() - ofrece un atajo si sabes que tu consulta devolverá sólo un objeto. - - - - Iterando los resultados - - - Ocasionalmente, podrías ser capaz de lograr mejor rendimiento al ejecutar la consulta - usando el método iterate(). Esto sólo será en el caso que esperes - que las instancias reales de entidad devueltas por la consulta estén ya en la sesión - o caché de segundo nivel. Si todavía no están en caché, iterate() - será más lento que list() y podría requerir muchas llamadas a la - base de datos para una consulta simple, usualmente 1 para la - selección inicial que solamente devuelve identificadores, y n - selecciones adicionales para inicializar las instancias reales. - - - - - - - Consultas que devuelven tuplas - - - Las consultas de Hibernate a veces devuelven tuplas de objetos, en cuyo caso - cada tupla se devuelve como un array: - - - - - - - - Resultados escalares - - - Las consultas pueden especificar una propiedad de una clase en la cláusula - select. Pueden incluso llamar a funciones de agregación SQL. - Las propiedades o agregaciones son considerados resultados "escalares" - (y no entidades en estado persistente). - - - - - - - - Ligación de parámetros - - - Se proveen métodos en Query para ligar valores a - parámetros con nombre o parámetros ? de estilo JDBC. - Al contrario de JDBC, Hibernate numera los parámetros desde cero. - Los parámetros con nombre son identificadores de la forma :name - en la cadena de la consulta. Las ventajas de los parámetros con nombre son: - - - - - - los parámetros con nombre son insensibles al orden en que aparecen - en la cadena de consulta - - - - - pueden aparecer múltiples veces en la misma consulta - - - - - son auto-documentados - - - - - - - - - - - - - - Paginación - - - Si necesitas especificar límites sobre tu conjunto resultado (el número máximo de filas - que quieras traer y/o la primera fila que quieras traer) debes usar los métodos de la - interface Query: - - - - - - Hibernate sabe cómo traducir este límite de consulta al SQL nativo de tu - DBMS. - - - - - - Iteración scrollable - - - Si tu driver JDBC soporta ResultSets scrollables, la - interface Query puede ser usada para obtener un objeto - ScrollableResults, que permite una navegación flexible - de los resultados de consulta. - - - i++ ) && cats.next() ) pageOfCats.add( cats.get(1) ); - -} -cats.close()]]> - - - Nota que se requiere una conexión de base de datos abierta (y cursor) para esta - funcionalidad, usa setMaxResult()/setFirstResult() - si necesitas la funcionalidad de paginación fuera de línea. - - - - - - Externalizando consultas con nombre - - - Puedes además definir consultas con nombre en el documento de mapeo. - (Recuerda usar una sección CDATA si tu consulta - contiene caracteres que puedan ser interpretados como etiquetado.) - - - ? -] ]>]]> - - - La ligación de parámetros y ejecución se hace programáticamente: - - - - - - Nota que el código real del programa es independiente del lenguaje de consulta - usado; puedes además definir consultas SQL nativas en metadatos, o migrar - consultas existentes a Hibernate colocándolas en ficheros de mapeo. - - - - - - - - Filtrando colecciones - - Un filtro de colección es un tipo especial de consulta que puede ser - aplicado a una colección persistente o array. La cadena de consulta puede referirse a - this, significando el elemento de colección actual. - - - - - - La colección devuelta es considerada un bag, y es una copia de la colección - dada. La colección original no es modificada (esto es contrario a la implicación - del nombre "filtro", pero consistente con el comportamiento esperado). - - - - Observa que los filtros no requieren una cláusula from (aunque pueden - tener uno si se requiere). Los filtros no están limitados a devolver los elementos de - colección por sí mismos. - - - - - - Incluso una consulta de filtro vacío es útil, por ejemplo, para cargar un - subconjunto de elementos en una colección enorme: - - - - - - - - Consultas de criterios - - - HQL es extremadamente potente pero algunos desarrolladores prefieren construir - consultas dinámicamente usando una API orientada a objetos, en vez construir - cadenas de consulta. Hibernate provee una API intuitiva de consulta Criteria - para estos casos: - - - - - - Las APIs de Criteria y la asociada Example - son discutidas en más detalle en . - - - - - - Consultas en SQL nativo - - - Puedes expresar una consulta en SQL, usando createSQLQuery() y - dejando que Hibernate cuide del mapeo de los conjuntos resultado a objetos. - Nota que puedes llamar en cualquier momento a session.connection() y - usar la Connection JDBC directamente. Si eliges usar la API de - Hibernate, debes encerrar los alias de SQL entre llaves: - - - - - - - - Las consultas SQL pueden contener parámetros con nombre y posicionales, al igual que - las consultas de Hibernate. Puede encontrarse más información sobre consultas en SQL - nativo en . - - - - - - - - Modificando objetos persistentes - - - Las instancias persistentes transaccionales (es decir, objetos cargados, - creados o consultados por la Session) pueden ser manipulados por la - aplicación y cualquier cambio al estado persistente será persistido cuando la Session - sea limpiada (flushed) (discutido más adelante en este capítulo). No hay - necesidad de llamar un método en particular (como update(), que tiene un - propósito diferente) para hacer persistentes tus modificaciones. De modo que la forma más - directa de actualizar el estado de un objeto es cargarlo con load(), - y entonces manipularlo directamente, mientras la Session está abierta: - - - - - - A veces este modelo de programación es ineficiente pues podría requerir una - SELECT de SQL (para cargar un objeto) y un UPDATE - de SQL (para hacer persistentes sus datos actualizados) en la misma sesión. Por lo tanto, - Hibernate ofrece un enfoque alternativo, usando instancias separadas (detached). - - - - Nota que Hibernate no ofreve su propia API para ejecución directa de - sentencias UPDATE o DELETE. Hibernate es un - servicio de gestión de estado, no tienes que pensar en - sentencias para usarlo. JDBC es una API perfecta para ejecutar - sentencias SQL; puedes obtener una Connection JDBC en cualquier - momento llamando a session.connection(). Además, la noción de - operaciones masivas entra en conflicto con el mapeo objeto/relacional en aplicaciones - en línea orientadas al procesamiento de transacciones. Versiones futuras de Hibernate - pueden, sin embargo, proveer funciones de operación masiva especiales. Ver - por algunos trucos de operación en lote (batch) posibles. - - - - - - - Modificando objetos separados - - - Muchas aplicaciones necesitan recuperar un objeto en una transacción, enviarla - a la capa de UI para su manipulación, y entonces salvar los cambios en una nueva - transacción. Las aplicaciones que usan este tipo de enfoque en un entorno de - alta concurrencia usualmente usan datos versionados para asegurar el aislamiento - de la unidad de trabajo "larga". - - - - Hibernate soporta este modelo al proveer re-unión de instancias separadas usando - los métodos Session.update() o Session.merge(): - - - - - - Si el Cat con identificador catId ya hubiera - sido cargado por secondSession cuando la aplicación intentó - volver a unirlo, se habría lanzado una excepción. - - - - Usa update() si no estás seguro que la sesión tenga - una instancia ya persistente con el mismo identificador, y merge() - si quieres fusionar tus modificaciones en cualquier momento sin consideración del - estado de la sesión. En otras palabras, update() es usualmente - el primer método que llamarías en una sesión fresca, asegurando que la re-unión de - tus instancias separadas es la primera operación que se ejecuta. - - - - La aplicación debe actualizar individualmente las instancias separadas alcanzables - por la instancia separada dada llamando a update(), si y - sólo si quiere que sus estados sean también actualizados. - Esto puede, por supuesto, ser automatizado usando persistencia transitiva, - ver . - - - - El método lock() también permite a una aplicación reasociar - un objeto con una sesión nueva. Sin embargo, la instancia separada no puede - haber sido modificada! - - - - - - Nota que lock() puede ser usado con varios LockModes, - ver la documentación de la API y el capítulo sobre manejo de transacciones para más - información. La re-unión no es el único caso de uso para lock(). - - - - Se discuten otros modelos para unidades de trabajo largas en . - - - - - - Detección automática de estado - - - Los usuarios de Hibernate han pedido un método de propósito general que bien - salve una instancia transitoria generando un identificador nuevo, o bien - actualice/reúna las instancias separadas asociadas con su identificador actual. - El método saveOrUpdate() implementa esta funcionalidad. - - - - - - El uso y semántica de saveOrUpdate() parece ser confuso para - usuarios nuevos. Primeramente, en tanto no estés intentando usar instancias de una - sesión en otra sesión nueva, no debes necesitar usar update(), - saveOrUpdate(), o merge(). Algunas aplicaciones - enteras nunca usarán ninguno de estos métodos. - - - - Usualmente update() o saveOrUpdate() se usan en - el siguiente escenario: - - - - - - la aplicación carga un objeto en la primera sesión - - - - - el objeto es pasado a la capa de UI - - - - - se hacen algunas modificaciones al objeto - - - - - el objeto se pasa abajo de regreso a la capa de negocio - - - - - la aplicación hace estas modificaciones persistentes llamando - a update() en una segunda sesión - - - - - - saveOrUpdate() hace lo siguiente: - - - - - - si el objeto ya es persistente en esta sesión, no hace nada - - - - - si otro objeto asociado con la sesión tiene el mismo identificador, - lanza una excepción - - - - - si el objeto no tiene ninguna propiedad identificadora, lo salva llamando a - save() - - - - - si el identificador del objeto tiene el valor asignado a un objeto recién - instanciado, lo salva llamando a save() - - - - - si el objeto está versionado (por un <version> o - <timestamp>), y el valor de la propiedad de versión - es el mismo valor asignado a una objeto recién instanciado, lo salva llamando - a save() - - - - - en cualquier otro caso se actualiza el objeto llamando a update() - - - - - - y merge() es muy diferente: - - - - - - si existe una instancia persistente con el mismo identificador asignado actualmente con la - sesión, copia el estado del objeto dado en la instancia persistente - - - - - si no existe ninguna instancia persistente actualmente asociada a la sesión, - intente cargarla de la base de datos, o crear una nueva instancia persistente - - - - - la instancia persistente es devuelta - - - - - la instancia dada no resulta ser asociada a la sesión, permanece separada - - - - - - - - Borrando objetos persistentes - - - Session.delete() quitará el estado de un objeto de la base de datos. - Por supuesto, tu aplicación podría tener aún una referencia a un objeto borrado. Lo mejor - es pensar en delete() como hacer transitoria una instancia persistente. - - - - - - Puedes borrar los objetos en el orden que gustes, sin riesgo de violaciones - de restricción de clave foránea. Aún es posible violar una restricción - NOT NULL sobre una columna clave foránea borrando objetos - en un orden erróneo, por ejemplo, si borras el padre, pero olvidas borrar los - hijos. - - - - - - Replicando objetos entre dos almacénes de datos diferentes - - - Es ocasionalmente útil ser capaz de tomar un grafo de instancias persistentes - y hacerlas persistentes en un almacén de datos diferente, sin regenerar los valores - identificadores. - - - - - - El ReplicationMode determina cómo replicate() - tratará los conflictos con filas existentes en la base de datos. - - - - - - ReplicationMode.IGNORE - ignora el objeto cuando existe una fila - de base de datos con el mismo identificador - - - - - ReplicationMode.OVERWRITE - sobrescribe cualquier fila de base de - datos existente con el mismo identificador - - - - - ReplicationMode.EXCEPTION - lanza una excepción si existe una fila - de base de datos con el mismo identificador - - - - - ReplicationMode.LATEST_VERSION - sobrescribe la fila si su número - de versión es anterior al número de versión del objeto, o en caso contrario ignora el objeto - - - - - - Los casos de uso para esta funcionalidad incluyen reconciliar datos ingresados en - instancias diferentes de bases de datos, actualizar información de configuración de - sistema durante actualizaciones de producto, deshacer cambios producidos durante - transacciones no-ACID y más. - - - - - - Limpiando (flushing) la sesión - - - Cada tanto, la Session ejecutará las sentencias SQL necesarias para - sincronizar el estado de la conexión JDBC con el estado de los objetos mantenidos en menoria. - Este proceso, limpieza (flush), ocurre por defecto en los siguientes - puntos - - - - - - antes de algunas ejecuciones de consulta - - - - - desde org.hibernate.Transaction.commit() - - - - - desde Session.flush() - - - - - - Las sentencias SQL son liberadas en el siguiente orden - - - - - - todas las inserciones de entidades, en el mismo orden que los objetos - correspondientes fueron salvados usando Session.save() - - - - - todas las actualizaciones de entidades - - - - - todas los borrados de colecciones - - - - - todos los borrados, actualizaciones e inserciones de elementos de colección - - - - - todas las inserciones de colecciones - - - - - todos los borrados de entidades, en el mismo orden que los objetos - correspondientes fueron borrados usando Session.delete() - - - - - - (Una excepción es que los objetos que usan generación de ID native - se insertan cuando son salvados.) - - - - Excepto cuando llamas explícitamente a flush(), no hay en absoluto - garantías sobre cuándo la Session ejecuta las - llamadas JDBC. sólo sobre el orden en que son ejecutadas. Sin embargo, - Hibernate garantiza que los métodos Query.list(..) nunca devolverán datos - añejos o erróneos. - - - - Es posible cambiar el comportamiento por defecto de modo que la limpieza (flush) - ocurra menos frecuentemente. La clase FlushMode tres modos - diferentes: sólo en tiempo de compromiso (y sólo cuando se use la API de - Transaction de Hibernate), limpieza automática usando la rutina - explicada, o nunca limpiar a menos que se llame a flush() - explícitamente. El último modo es útil para unidades de trabajo largas, donde una - Session se mantiene abierta y desconectada por largo tiempo - (ver ). - - - - - - Durante la limpieza, puede ocurrir una excepción (por ejemplo, si una operación DML - violase una restricción). Ya que el manejo de excepciones implica alguna comprensión - del comportamiento transaccional de Hibernate, lo discutimos en . - - - - - - Persistencia transitiva - - - Es absolutamente incómodo dalvar, borrar, o reunir objetos individuales, - especialmente si tratas con un grafo de objetos asociados. Un caso común es - una relación padre/hijo. Considera el siguiente ejemplo: - - - - Si los hijos en una relación padre/hijo pudieran ser tipificados en valor - (por ejemplo, una colección de direcciones o cadenas), sus ciclos de vida - dependerían del padre y se requeriría ninguna otra acción para el tratamiento - en "cascada" de cambios de estado. Cuando el padre es salvado, los objetos hijo - tipificados en valor son salvados también, cuando se borra el padre, se borran - los hijos, etc. Esto funciona incluso para operaciones como el retiro de un - hijo de la colección. Hibernate detectará esto y, ya que los objetos tipificados - en valor no pueden tener referencias compartidas, borrará el hijo de la base - de datos. - - - - Ahora considera el mismo escenario con los objetos padre e hijos siendo entidades, - no tipos de valor (por ejemplo, categorías e ítems, o gatos padre e hijos). - Las entidades tienen su propio ciclo de vida, soportan referencias compartidas - (de modo que quitar una entidad de una colección no significa que sea borrada), - y no hay por defecto ningún tratamiento en "cascada" de estado de una entidad - a otras entidades asociadas. Hibernate no implementa persistencia por - alcance. - - - - Para cada operación básica de la sesión de Hibernate - incluyendo persist(), merge(), - saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - hay un estilo - de cascada correspondiente. Respectivamente, los estilos de cascada se llaman create, - merge, save-update, delete, lock, refresh, evict, replicate. Si quieres que una - operación sea tratada en cascada a lo largo de una asociación, debes indicar eso en el - documento de mapeo. Por ejemplo: - - - ]]> - - - Los estilos de cascada pueden combinarse: - - - ]]> - - - Puedes incluso usar cascade="all" para especificar que todas - las operaciones deben ser tratadas en cascada a lo largo de la asociación. El por defecto - cascade="none" especifica que ninguna operación será tratada en cascada. - - - - Un estilo de cascada especial, delete-orphan, se aplica sólo a - asociaciones uno-a-muchos, e indica que la operación delete() debe - aplicarse a cualquier objeto hijo que sea quitado de la asociación. - - - - - Recomendaciones: - - - - - - Usualmente no tiene sentido habilitar el tratamiento en cascada a una asociación - <many-to-one> o <many-to-many>. - El tratamiento en cascada es frecuentemente útil para las asociaciones - <one-to-one> y <one-to-many>. - associations. - - - - - Si la esperanza de vida de los objetos hijos está ligada a la eesperanza de - vida del objeto padre, házlo un objeto de ciclo de vida - especificando cascade="all,delete-orphan". - - - - - En otro caso, puede que no necesites tratamiento en cascada en absoluto. Pero - si piensas que estarás trabajando frecuentemente con padre e hijos juntos en la - misma transacción, y quieres ahorrarte algo de tipeo, considera usar - cascade="persist,merge,save-update". - - - - - - Mapear una asociación (ya sea una asociación monovaluada, o una colección) con - cascade="all" marca la asociación como una relación del estilo - padre/hijo donde save/update/delete en el padre resulta - en save/update/delete del hijo o hijos. - - - Además, una mera referencia a un hijo desde un padre persistente resultará en - un save/update del hijo. Esta metáfora está incompleta, sin embargo. Un hijo - que deje de ser referenciado por su padre no es borrado - automáticamente, excepto en el caso de una asociación <one-to-many> - mapeada con cascade="delete-orphan". La semántica precisa de - las operaciones en cascada para una relación padre/hijo es: - - - - - - Si un padre le es pasado a persist(), todos los hijos le son - pasados a persist() - - - - - Si un padre le es pasado a merge(), todos los hijos le son - pasados a merge() - - - - - Si un padre le es pasado a save(), update() o - saveOrUpdate(), todos los hijos le son pasados a saveOrUpdate() - - - - - Si un hijo transitorio o separado se vuelve referenciado por un padre - persistente, le es pasado a saveOrUpdate() - - - - - Si un padre es borrado, todos los hijos le son pasados a delete() - - - - - Si un hijo deja de ser referenciado por un padre persistente, - no ocurre nada especial - la aplicación debe - borrar explícitamente el hijo de ser necesario - a menos que - cascade="delete-orphan", en cuyo caso el hijo - "huérfano" es borrado. - - - - - - - - Usando metadatos - - - Hibernate requiere de un modelo de meta-nivel muy rico de todas las entidades y tipos de valor. - De vez en cuando, este modelo es muy útil para la aplicación misma. Por ejemplo, la aplicación - podría usar los metadatos de Hibernate para implementar un algoritmo "inteligente" de copia - en profundidad que entienda qué objetos deben ser copiados (por ejemplo, tipo de valor mutables) - y cuáles no (por ejemplo, tipos de valor inmutables y, posiblemente, entidades asociadas). - - - Hibernate expone los metadatos vía las interfaces ClassMetadata y - CollectionMetadata y la jerarquía Type. Las instancias - de las interfaces de metadatos pueden obtenerse de SessionFactory. - - - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/toolset_guide.xml b/documentation/manual/es-ES/src/main/docbook/modules/toolset_guide.xml deleted file mode 100644 index a6efd9a11b..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/toolset_guide.xml +++ /dev/null @@ -1,459 +0,0 @@ - - Guía del Conjunto de Herramientas - - - La ingeniería de ida y vuelta con Hibernate es posible usando un conjunto de plugins de Eclipse, - herramientas de línea de comandos, así como tareas de Ant. - - - - Las Herramientas de Hibernate actualmente incluyen plugins para la IDE de - Eclipse así como tareas de Ant para la ingeniería inversa de bases de datos existentes: - - - - - Editor de Mapeo: Un editor de ficheros de mapeo XML, que soporta autocompleción - y resaltado de sintáxis. Soporta también autocompleción semántica de nombres de clases y nombres de - campos/propiedades, haciéndolo mucho más versátil que un editor de XML normal. - - - Consola: La consola es una nueva vista en Eclipse. Además de la vista de - árbol de tus configuraciones de consola, tienes también una vista interactiva de tus clases - persistentes y sus relaciones. La console te permite ejecutar consultas HQL contra tu base de datos y - navegar el resultado directamente en Eclipse. - - - Asistentes de Desarrollo: Se proveen muchos asistentes con las herramientas - de Eclipse. Puedes usar un asistente para generar rápidamente ficheros de configuración de Hibernate - (cfg.xml), o incluso puedes haceruna ingeniería inversa completa de un esquema de base de datos existente - en ficheros de código de POJO y ficheros de mapeo de Hibernate. El asistente de ingeniería inversa soporta - plantillas personalizables. - - - Tareas de Ant: - - - - - - Por favor refiérete al paquete Herramientas de Hibernate y su documentación para - más información. - - - - Sin embargo, el paquete principal de Hibernate viene incluyendo una herramienta integrada - (puede ser usada incluso "dentro" de Hibernate on-the-fly): SchemaExport - también conocido como hbm2ddl. - - - - Generación automática de esquemas - - - Una utilidad de Hibernate puede generar DDL desde tus ficheros de mapeo. El esquema generado incluye - restricciones de integridad referencial (claves primarias y foráneas) para las tablas de entidades y - colecciones. Las tablas y secuencias también son creadas para los generadores de identificadores mapeados. - - - - Debes especificar un Dialecto SQL vía la propiedad - hibernate.dialect al usar esta herramienta, ya que el DDL es altamente específico del - vendedor. - - - - First, customize your mapping files to improve the generated schema. - - - - Personalizando el esquema - - - Muchos elementos de mapeo de Hibernate definen un atributo opcional llamado length. - Con este atributo puedes establecer el tamaño de una columna. (O, para tipos de datos - numéricos/decimales, la precisión.) - - - - Algunas etiquetas también aceptan un atributo not-null (para generar una restricción - NOT NULL en columnas de tablas) y y un atributo unique (para generar - restricciones UNIQUE en columnas de tablas). - - - - Algunas etiquetas aceptan un atributo index para especificar el nombre de un índice - para esa columna. Se puede usar un atributo unique-key para agrupar columnas en una - restricción de clave de una sola unidad. Actualmente, el valor especificado del atributo - unique-key no es usado para nombrar la restricción, sólo para - agrupar las columnas en el fichero de mapeo. - - - - Ejemplos: - - - - - - -]]> - - - Alternativamente, estos elementos aceptan tambíen un elemento hijo <column>. - Esto es particularmente útil para tipos multicolumnas: - - - - -]]> - - - - - -]]> - - - El atributo sql-type permite al usuario sobrescribir el mapeo por defecto de - tipo Hibernate a tipo de datos SQL. - - - - El atributo check te permite especificar una comprobación de restricción. - - - - -]]> - - - ... - -]]> - - - - Resumen - - - - - - - Atributo - Valores - Interpretación - - - - - length - number - largo de columna/precisión decimal - - - not-null - true|false - especifica que la columna debe ser no nulable - - - unique - true|false - especifica que la columna debe tener una restricción de unicidad - - - index - index_name - especifica el nombre de un índice (multicolumna) - - - unique-key - unique_key_name - especifica el nombre de una restricción de unicidad multicolumna - - - foreign-key - foreign_key_name - - especifica el nombre de la restricción de clave foránea generada por una - asociación, úsalo en los elementos de mapeo <one-to-one>, <many-to-one>, - <key>, y <many-to-many>. Nota que los lados - inverse="true" no serán considerados por - SchemaExport. - - - - sql-type - column_type - - sobrescribe el tipo de columna por defecto (sólo atributo del elemento - <column>) - - - - check - expresión SQL - - crea una restricción de comprobación SQL en columna o tabla - - - - -
- - - El elemento <comment> te permite especificar un comentario para el esquema - generado. - - - - Current customers only - ... -]]> - - - - Balance in USD - -]]> - - - Esto resulta en una sentencia comment on table o comment on column - en el DDL generado (donde esté soportado). - - -
- - - Ejecutando la herramienta - - - La herramienta SchemaExport escribe un guión DDL a la salida estándar y/o - ejecuta las sentencias DDL. - - - - java -cp classpaths_de_hibernate - org.hibernate.tool.hbm2ddl.SchemaExport opciones ficheros_de_mapeo - - - - Opciones de Línea de Comandos de <literal>SchemaExport</literal> - - - - - - Opción - Descripción - - - - - --quiet - no enviar a salida estándar el guión - - - --drop - sólo desechar las tablas - - - --text - no exportar a la base de datos - - - --output=my_schema.ddl - enviar la salida del guión ddl a un fichero - - - --config=hibernate.cfg.xml - lee la configuración de Hibernate de un fichero XML - - - --properties=hibernate.properties - lee las propiedades de base de datos de un fichero - - - --format - formatea agradablemente el SQL generado en el guión - - - --delimiter=x - establece un delimitador de fin de línea para el guión - - - -
- - - Puedes incluso encajar SchemaExport en tu aplicación: - - - - -
- - - Propiedades - - - Las propiedades de base de datos pueden especificarse - - - - - como propiedades de sistema con -D<property> - - - en hibernate.properties - - - en un fichero de propiedades mencionado con --properties - - - - - Las propiedades necesarias son: - - - - Propiedades de Conexión de SchemaExport - - - - - - Nombre de Propiedad - Descripción - - - - - hibernate.connection.driver_class - clase del driver jdbc - - - hibernate.connection.url - url de jdbc - - - hibernate.connection.username - usuario de base de datos - - - hibernate.connection.password - contraseña de usuario - - - hibernate.dialect - dialecto - - - -
- -
- - - Usando Ant - - - Puedes llamar a SchemaExport desde tu guión de construcción de Ant: - - - - - - - - - - -]]> - - - - - Actualizaciones incrementales de esquema - - - La herramienta SchemaUpdate actualizará un esquema existente con cambios - "incrementales". Nota que SchemaUpdate depende fuertemente de la API de metadatos - de JDBC, de modo que no funcionará con todos los drivers JDBC. - - - - java -cp classpaths_de_hibernate - org.hibernate.tool.hbm2ddl.SchemaUpdate opciones ficheros_de_mapeo - - - - Opciones de Línea de Comandos de <literal>SchemaUpdate</literal> - - - - - - Opción - Descripción - - - - - --quiet - no enviar a salida estándar el guión - - - --properties=hibernate.properties - lee las propiedades de base de datos de un fichero - - - -
- - - Puedes encajar SchemaUpdate en tu aplicación: - - - - -
- - - Usando Ant para actualizaciones incrementales de esquema - - - Puedes llamar a SchemaUpdate desde el guión de Ant: - - - - - - - - - - -]]> - - - -
- -
- diff --git a/documentation/manual/es-ES/src/main/docbook/modules/transactions.xml b/documentation/manual/es-ES/src/main/docbook/modules/transactions.xml deleted file mode 100644 index c3e1e62036..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/transactions.xml +++ /dev/null @@ -1,925 +0,0 @@ - - Transacciones y Concurrencia - - - El punto más importante sobre Hibernate y el control de concurrencia es que muy fácil - de comprender. Hibernate usa directamente conexiones JDBC y recursos JTA sin agregar - ningún comportamiento de bloqueo adicional. Recomendamos altamente que gastes algo de - tiempo con la especificación de JDBC, ANSI, y el aislamiento de transacciones de tu sistema - de gestión de base de datos. Hibernate sólo añade versionado automático pero no bloquea - objetos en memoria ni cambia el nivel de aislamiento de tus transacciones de base de datos. - Básicamente, usa Hibernate como usarías JDBC directo (o JTA/CMT) con tus recursos de base de - datos. - - - - Sin embargo, además del versionado automático, Hibernate ofrece una API (menor) para - bloqueo pesimista de filas, usando la sintáxis SELECT FOR UPDATE. - Esta API se discute más adelante en este capítulo: - - - - Comenzamos la discusión del control de concurrencia en Hibernate con la granularidad - de Configuration, SessionFactory, y - Session, así como la base de datos y las transacciones de aplicación - largas. - - - - Ámbitos de sesión y de transacción - - - Una SessionFactory es un objeto seguro entre hebras caro-de-crear - pensado para ser compartido por todas las hebras de la aplicación. Es creado una sola vez, - usualmente en el arranque de la aplicación, a partir de una instancia de Configuration. - - - - Una Session es un objeto barato, inseguro entre hebras que debe - ser usado una sola vez, para un solo proceso de negocio, una sola unidad de trabajo, - y luego descartado. Una Session no obtendrá una Connection - JDBC (o un Datasource) a menos que sea necesario, de modo que puedas - abrir y cerrar seguramente una Session incluso si no estás seguro - que se necesitará acceso a los datos para servir una petición en particular. (Esto se - vuelve importante en cuanto estés implementando alguno de los siguientes patrones usando - intercepción de peticiones). - - - - Para completar este cuadro tienes que pensar también en las transacciones de base de - datos. Una transacción de base de datos tiene que ser tan corta como sea posible, para - reducir la contención de bloqueos en la base de datos. Las transacciones largas de base de - datos prevendrán a tu aplicación de escalar a una carga altamente concurrente. - - - - ¿Qué es el ámbito de una unidad de trabajo? ¿Puede una sola Session de Hibernate - extenderse a través de varias transacciones de base de datos o es ésta una relación uno-a-uno - de ámbitos? ¿Cuándo debes abrir y cerrar una Session y cómo demarcas los - límites de la transacción de base de datos? - - - - Unidad de trabajo - - - Primero, no uses el antipatrón sesión-por-operación, esto es, - ¡no abras y cierres una Session para cada simple llamada a la base - de datos en una sola hebra! Por supuesto, lo mismo es verdad para transacciones de base de - datos. Las llamadas a base de datos en una aplicación se hacen usando una secuencia - prevista, que están agrupadas dentro de unidades de trabajo atómicas. (Nota que esto - también significa que el auto-commit después de cada una de las sentencias SQL es inútil - en una aplicación, este modo está pensado para trabajo ad-hoc de consola SQL. - Hibernate deshabilita, o espera que el servidor de aplicaciones lo haga, el modo - auto-commit inmediatamente.) - - - - El patrón más común en una aplicación mutiusuario cliente/servidor es - sesión-por-petición. En este modelo, una petición del cliente - es enviada al servidor (en donde se ejecuta la capa de persistencia de Hibernate), - se abre una nueva Session de Hibernate, y todas las operaciones - de base de datos se ejecutan en esta unidad de trabajo. Una vez completado el trabajo - (y se ha preparado la respuesta para el cliente) la sesión es limpiada y cerrada. - Podrías usar una sola transacción de base de datos para servir a petición del cliente, - comenzándola y comprometiéndola cuando abres y cierras la Session. - La relación entre las dos es uno-a-uno y este modelo es a la medida perfecta de muchas - aplicaciones. - - - - El desafío yace en la implementación: no sólo tienen que comenzarse y terminarse correctamente - la Session y la transacción, sino que además tienen que estar accesibles - para las operaciones de acceso a datos. La demarcación de una unidad de trabajo se implementa - idealmente usando un interceptor que se ejecuta cuando una petición llama al servidor y anter que - la respuesta sea enviada (es decir, un ServletFilter). Recomendamos ligar la - Session a la hebra que atiende la petición, usando una variable - ThreadLocal. Esto permite un fácil acceso (como acceder a una variable static) - en tódo el código que se ejecuta en esta hebra. Dependiendo del mecanismo de demarcación de - transacciones de base de datos que elijas, podrías mantener también el contexto de la transacción - en una variable ThreadLocal. Los patrones de implementación para esto son - conocidos como Sesión Local de Hebra (ThreadLocal Session) y - Sesión Abierta en Vista (Open Session in View). Puedes extender fácilmente - la clase de ayuda HibernateUtil mostrada anteriormente para encontrar - una forma de implementar un interceptor e instalarlo en tu entorno. Ver el sitio web de Hibernate - para consejos y ejemplos. - - - - - - Transacciones de aplicación - - - El patrón sesión-por-petición no es el único concepto útil que puedes usar para diseñar unidades - de trabajo. Muchos procesos de negocio requiere una serie completa de interacciones con el - usuario intercaladas con accesos a base de datos. En aplicaciones web y de empresa no es aceptable - que una transacción de base de datos se extienda a través de la interacción de un usuario. - Considera el siguiente ejemplo: - - - - - - Se abre la primera pantalla de un diálogo, los datos vistos por el usuario han sido - cargados en una Session y transacción de base de datos particular. - El usuario es libre de modificar los objetos. - - - - - El usuario hace click en "Salvar" después de 5 minutos y espera que sus modificaciones - sean hechas persistentes. También espera que él sea la única persona editando esta - información y que no puede ocurrir ninguna modificación en conflicto. - - - - - - Llamamos a esto unidad de trabajo, desde el punto de vista del usuario, una larga - transacción de aplicación ejecutándose. Hay muchas formas en - que puedes implementar esto en tu aplicación. - - - - Una primera implementación ingenua podría mantener abierta la Session - y la transacción de base de datos durante el tiempo de pensar del usuario, con bloqueos - tomados en la base de datos para prevenir la modificación concurrente, y para garantizar - aislamiento y atomicidad. Esto es, por supuesto, un antipatrón, ya que la contención de - bloqueo no permitiría a la aplicación escalar con el número de usuarios concurrentes. - - - - Claramente, tenemos que usar muchas transacciones de base de datos para implementar la transacción - de aplicación. En este caso, mantener el aislamiento de los procesos de negocio se vuelve una - responsabilidad parcial de la capa de aplicación. Una sola transacción de aplicación usualmente - abarca varias transacciones de base de datos. Será atómica si sólo una de estas transacciones de - base de datos (la última) almacena los datos actualizados, todas las otras simplemente leen datos - (por ejemplo, en un diálogo estilo-asistente abarcando muchos ciclos petición/respuesta). - Esto es más fácil de implementar de lo que suena, especialmente si usas las funcionalidades de - Hibernate: - - - - - - Versionado Automático - Hibernate puede llevar un control automático de - concurrencia optimista por ti, puede detectar automáticamente si una modificación concurrente - ha ocurrido durante el tiempo de pensar del usuario. - - - - - Objetos Separados - Si decides usar el ya discutido patrón - de sesión-por-petición, todas las instancias cargadas estarán - en estado separado durante el tiempo de pensar del usuario. Hibernate te permite - volver a unir los objetos y hacer persistentes las modificaciones. El patrón se - llama sesión-por-petición-con-objetos-separados. Se usa - versionado automático para aislar las modificaciones concurrentes. - - - - - Sesión Larga - La Session de Hibernate puede ser - desconectada de la conexión JDBC subyacente después que se haya sido comprometida la - transacción de base de datos, y reconectada cuando ocurra una nueva petición del cliente. - Este patrón es conocido como sesión-por-transacción-de-aplicación - y hace la re-unión innecesaria. Para aislar las modificaciones concurrentes se usa el - versionado automático. - - - - - - Tanto sesión-por-petición-con-objetos-separados como - sesión-por-transacción-de-aplicación, ambas tienen - ventajas y desventajas, las discutimos más adelante en este capítulo en el contexto - del control optimista de concurrencia. - - - - - - Considerando la identidad del objeto - - - Una aplicación puede acceder concurrentemente a el mismo estado persistente en dos - Sessions diferentes. Sin embargo, una instancia de una clase - persistente nunca se comparte entre dos instancias de Session. - Por lo tanto existen dos nociones diferentes de identidad: - - - - - Identidad de Base de Datos - - - foo.getId().equals( bar.getId() ) - - - - - Identidad JVM - - - foo==bar - - - - - - - Entonces para objetos unidos a una Session en particular - (es decir en el ámbito de una Session) las dos nociones son equivalentes, y - la identidad JVM para la identidad de base de datos está garantizada por Hibernate. Sin embargo, - mientras la aplicación acceda concurrentemente al "mismo" (identidad persistente) objeto de negocio - en dos sesiones diferentes, las dos instancias serán realmente "diferentes" (identidad JVM). - Los conflictos se resuelven (con versionado automático) en tiempo de limpieza (flush) usando un - enfoque optimista. - - - - Este enfoque deja que Hibernate y la base de datos se preocupen sobre la concurrencia. Además - provee la mejor escalabilidad, ya que garantizando la identidad un unidades de trabajo monohebra - no se necesitan bloqueos caros u otros medios de sincronización. La aplicación nunca necesita - sincronizar sobre ningún objeto de negocio, siempre que se apegue a una sola hebra por - Session. Dentro de una Session la aplicación puede usar - con seguridad == para comparar objetos. - - - - Sin embargo, una aplicación que usa == fuera de una Session, - podría ver resultados inesperados. Esto podría ocurrir incluso en sitios algo inesperados, - por ejemplo, si pones dos instancias separadas dentro del mismo Set. - Ambas podrían tener la misma identidad de base de datos (es decir, representar la misma fila), - pero la identidad JVM, por definición, no está garantizada para las instancias en estado separado. - El desarrollador tiene que sobrescribir los métodos equals() y - hashCode() en las clases persistentes e implementar su propia noción de igualdad - de objetos. Hay una advertencia: Nunca uses el identificador de base de datos para implementar - la igualdad, usa una clave de negocio, una combinación de atributos únicos, usualmente inmutables. - El identificador de base de datos cambiará si un objeto transitorio es hecho persistente. - Si la instancia transitoria (usualmente junta a instancias separadas) es mantenida en un - Set, cambiar el código hash rompe el contrato del Set. - Los atributos para las claves de negocio no tienen que ser tan estables como las claves primarias - de base de datos, sólo tienes que garantizar estabilidad en tanto los objetos estén en el mismo - Set. Mira el sitio web de Hibernate para una discusión más cuidadosa de este - tema. Nota también que éste no es un tema de Hibernate, sino simplemente cómo la identidad y la igualdad - de los objetos Java tiene que ser implementada. - - - - - - Temas comunes - - - Nunca uses los antipatrones sesión-por-sesión-de-usuario o - sesión-por-aplicación (por supuesto, hay raras excepciones a esta - regla). Nota que algunis de los siguientes temas podrían también aparecer con los patrones - recomendados. Asegúrate que entiendes las implicaciones antes de tomar una decisión de - diseño: - - - - - - Una Session no es segura entre hebras. Las cosas que se suponen - que funcionan concurrentemente, como peticiones HTTP, beans de sesión, o workers de - Swing, provocarán condiciones de competencia si una instancia de Session - fuese compartida. Si guardas tu Session de Hibernate en tu - HttpSession (discutido más adelante), debes considerar sincronizar - el acceso a tu sesión HTTP. De otro modo, un usuario que hace click lo suficientemente - rápido puede llegar a usar la misma Session en dos hebras ejecutándose - concurrentemente. - - - - - Una excepción lanzada por Hibernate significa que tienes que deshacer (rollback) tu - transacción de base de datos y cerrar la Session inmediatamente - (discutido en más detalle luego). Si tu Session está ligada a la - aplicación, tienes que parar la aplicación. Deshacer (rollback) la transacción de base - de datos no pone a tus objetos de vuelta al estado en que estaban al comienzo de la - transacción. Esto significa que el estado de la base de datos y los objetos de negocio - quedan fuera de sincronía. Usualmente esto no es un problema, pues las excepciones no - son recuperables y tienes que volver a comenzar después del rollback de todos modos. - - - - - La Session pone en caché todo objeto que esté en estado persistente - (vigilado y chequeado por estado sucio por Hibernate). Esto significa que crece sin - fin hasta que obtienes una OutOfMemoryException, si la mantienes abierta por un largo - tiempo o simplemente cargas demasiados datos. Una solución para esto es llamar a - clear() y evict() para gestionar el caché de la - Session, pero probalemente debas considerar un procedimiento almacenado - si necesitas operaciones de datos masivas. Se muestran algunas soluciones en - . Mantener una Session abierta por la duración - de una sesión de usuario significa también una alta probabilidad de datos añejos. - - - - - - - - - - Demarcación de la transacción de base de datos - - - Los límites de las transacciones de base de datos (o sistema) son siempre necesarios. Ninguna comunicación - con la base de datos puede darse fuera de una transacción de base de datos (esto parece confundir muchos - desarrolladores acostumbrados al modo auto-commit). Siempre usa límites de transacción claros, incluso - para las operaciones de sólo lectura. Dependiendo del nivel de aislamiento y las capacidades de base de - datos, esto podría o no ser requerido, pero no hay un merma si siempre demarcas explícitamente - las transacciones. - - - - Una aplicación Hibernate puede ejecutarse en entornos no manejados (es decir, como independiente, - Web simple, o aplicaciones Swing) y entornos manejados J2EE. En un entorno no manejado, Hibernate es - usualmente responsable de su propio pool de conexiones de base de datos. El desarrollador de aplicaciones - tiene que establecer manualmente los límites de transacción, en otras palabras, hacer begin, commit, o - rollback las transacciones de base de datos por sí mismo. Un entorno manejado usualmente provee transacciones - gestionadas por contenedor, con el ensamble de transacción definido declarativamente en descriptores de - despliegue de beans de sesión EJB, por ejemplo. La demarcación programática de transacciones no es más - necesario, incluso limpiar (flush) la Session es hecho automáticamente. - - - - Sin embargo, frecuentemente es deseable mantener portable tu capa de persistencia. Hibernate ofrece - una API de envoltura llamada Transaction que se traduce al sistema de transacciones - nativo de tu entorno de despliegue. Esta API es realmente opcional, pero recomendamos fuertemente su uso - salvo que estés en un bean de sesión CMT. - - - - Usualmente, finalizar una Session implica cuatro fases distintas: - - - - - - limpiar (flush) la sesión - - - - - comprometer la transacción - - - - - cerrar la sesión - - - - - manejar excepciones - - - - - - Limpiar la sesión ha sido discutido anteriormente, tendremos ahora una mirada más de cerca - a la demarcación de transacciones y manejo de excepciones en sendos entornos manejado y no manejados. - - - - - Entorno no manejado - - - Si una capa de persistencia Hibernate se ejecuta en un entorno no manejado, las conexiones - de base de datos son manejadas usualmente por el mecanismo de pooling de Hibernate. El idioma - manejo de sesión/transacción se ve así: - - - - - - No tienes que limpiar con flush() la Session explícitamente - - la llamada a commit() automáticamente dispara la sincronización. - - - - Una llamada a close() marca el fin de una sesión. La principal implicación - de close() es que la conexión JDBC será abandonada por la sesión. - - - - Este código Java es portable y se ejecuta tanto en entornos no manejados como en entornos JTA. - - - - Muy probablemente nunca veas este idioma en código de negocio en una aplicación normal; - las excepciones fatales (sistema) deben siempre ser capturadas en la "cima". En otras palabras, - el código que ejecuta las llamadas de Hibernate (en la capa de persistencia) y el código que - maneja RuntimeException (y usualmente sólo puede limpiar y salir) están en - capas diferentes. Esto puede ser un desafío de diseñarlo tú mismo y debes usar los servicios - de contenedor J2EE/EJB en cuanto estuviesen disponibles. El manejo de excepciones se dicute - más adelante en este capítulo. - - - - Nota que debes seleccionar org.hibernate.transaction.JDBCTransactionFactory - (que es el por defecto). - - - - - - Usando JTA - - - Si tu capa de persistencia se ejecuta en un servidor de aplicaciones (por ejemplo, detrás - de beans de sesión EJB), cada conexión de datasource obtenida por Hibernate será parte - automáticamente de la transacción JTA global. Hibernate ofrece dos estrategias para esta - integración. - - - - Si usas transacciones gestionadas-por-bean (BMT) Hibernate le dirá al servidor de aplicaciones - que comience y finalice una transacción BMT si usas la API de Transaction. - De modo que, el código de gestión de la transacción es idéntico al de un entorno no manejado. - - - - - - Con CMT, la demarcación de la transacción se hace en descriptores de despliegue de beans de sesión, - no programáticamente. Si no quieres limpiar (flush) y cerrar manualmente la Session - por ti mismo, solamente establece hibernate.transaction.flush_before_completion a - true, hibernate.connection.release_mode a - after_statement o auto y - hibernate.transaction.auto_close_session a true. Hibernate - limpiará y cerrará entonces automáticamente la Session para ti. Lo único que resta - es deshacer (rollback) la transacción cuando ocurra una excepción. Afortunadamente, en un bean CMT, - incluso esto ocurre automáticamente, ya que una RuntimeException no manejada - disparada por un método de un bean de sesión le dice al contenedor que ponga a deshacer la transacción - global. Esto significa que, en CMT, no necesitas usar en absoluto la API de - Transaction de Hibernate. - - - - Nota que debes elegir org.hibernate.transaction.JTATransactionFactory en un - bean de sesión BMT, y org.hibernate.transaction.CMTTransactionFactory en un - bean de sesión CMT, cuando configures la fábrica de transacciones de Hibernate. Recuerda además - establecer org.hibernate.transaction.manager_lookup_class. - - - - Si trabajas en un entorno CMT, y usas limpieza (flushing) y cierre automáticos de la sesión, - podrías querer también usar la misma sesión en diferentes partes de tu código. Típicamente, - en un entorno no manejado, usarías una variable ThreadLocal para tener la sesión, - pero una sola petición de EJB puede ejecutarse en diferentes hebras (por ejemplo, un bean de sesión - llamando a otro bean de sesión). Si no quieres molestarte en pasar tu Session - por alrededor, la SessionFactory provee el método - getCurrentSession(), que devuelve una sesión que está pegada al contexto de - transacción JTA. ¡Esta es la forma más fácil de integrar Hibernate en una aplicación! - La sesión "actual" siempre tiene habilitados limpieza, cierre y liberación de conexión automáticos - (sin importar la configuración de las propiedades anteriores). Nuestra idioma de gestión de - sesión/transacción se reduce a: - - - - - - En otras palabras, todo lo que tienes que hacer en un entorno manejado, es llamar a - SessionFactory.getCurrentSession(), hacer tu trabajo de acceso a datos, - y dejar el resto al contenedor. Los límites de transacción se establecen declarativamente - en los descriptores de despliegue de tu bean de sesión. El ciclo de vida de la sesión es - manejado completamente por Hibernate. - - - - Existe una advertencia al uso del modo de liberación de conexión after_statement. - Debido a una limitación tonta de la especificación de JTA, no es posible para Hibernate - limpiar automáticamente ningún ScrollableResults no cerrado ni - instancias de Iterator devueltas por scroll() o - iterate(). Debes liberar el cursor de base de datos - subyacente llamando a ScrollableResults.close() o - Hibernate.close(Iterator) explícitamente desde un bloque finally. - (Por supuesto, la mayoría de las aplicaciones pueden evitarlo fácilmente no usando en absoluto ningún - scroll() o iterate() desde el código CMT.) - - - - - - Manejo de excepciones - - - Si la Session lanza una excepción (incluyendo cualquier - SQLException), debes inmediatamente deshacer (rollback) la - transacción de base de datos, llamar a Session.close() y - descartar la instancia de Session. Ciertos métodos de - Session no dejarán la sesión en un - estado consistente. Ninguna excepción lanzada por Hibernate puede ser tratada - como recuperable. Asegúrate que la Session sea cerrada llamando - a close() en un bloque finally. - - - - La HibernateException, que envuelve la mayoría de los errores que - pueden ocurrir en la capa de persistencia de Hibernate, en una excepción no chequeada - (no lo era en versiones anteriores de Hibernate). En nuestra opinión, no debemos forzar - al desarrollador de aplicaciones a capturar una excepción irrecuperable en una capa baja. - En la mayoría de los sistemas, las excepciones no chequeadas y fatales son manejadas - en uno de los primeros cuadros de la pila de llamadas a métodos (es decir, en las capas - más altas) y se presenta un mensaje de error al usuario de la aplicación (o se toma alguna - otra acción apropiada). Nota que Hibernate podría también lanzar otras excepciones no chequeadas - que no sean una HibernateException. Una vez más, no son recuperables y debe - tomarse una acción apropiada. - - - - Hibernate envuelve SQLExceptions lanzadas mientras se interactúa con la base - de datos en una JDBCException. De hecho, Hibernate intentará convertir la excepción - en una subclase de JDBCException más significativa. La SQLException - está siempre disponible vía JDBCException.getCause(). Hibernate convierte la - SQLException en una subclase de JDBCException apropiada usando - el SQLExceptionConverter adjunto a la SessionFactory. Por defecto, - el SQLExceptionConverter está definido para el dialecto configurado; sin embargo, - es también posible enchufar una implementación personalizada (ver los javadocs de la clase - SQLExceptionConverterFactory para los detalles). Los subtipos estándar de - JDBCException son: - - - - - - JDBCConnectionException - indica un error con la comunicación JDBC subyacente. - - - - - SQLGrammarException - indica un problema de gramática o sintáxis con el - SQL publicado. - - - - - ConstraintViolationException - indica alguna forma de violación de restricción - de integridad. - - - - - LockAcquisitionException - indica un error adquiriendo un nivel de bloqueo - necesario para realizar una operación solicitada. - - - - - GenericJDBCException - una excepción genérica que no cayó en ninguna de las - otras categorías. - - - - - - - - - - - Control optimista de concurrencia - - - El único enfoque que es consistente con alta concurrencia y alta escalabilidad es el control - optimista de concurrencia con versionamiento. El chuequeo de versión usa números de versión, - o timestamps, para detectar actualizaciones en conflicto (y para prevenir actualizaciones perdidas). - Hibernate provee para tres enfoques posibles de escribir código de aplicación que use concurrencia - optimista. Los casos de uso que hemos mostrado están en el contexto de transacciones de aplicación - largas pero el chequeo de versiones tiene además el beneficio de prevenir actualizaciones perdidas - en transacciones de base de datos solas. - - - - Chequeo de versiones de aplicación - - - En una implementación sin mucha ayuda de Hibernate, cada interacción con la base de datos ocurre en una - nueva Session y el desarrollador es responsable de recargar todas las intancias - persistentes desde la base de datos antes de manipularlas. Este enfoque fuerza a la aplicación a - realizar su propio chequeo de versiones para asegurar el aislamiento de transacciones de base de datos. - Es el enfoque más similar a los EJBs de entidad. - - - - - - La propiedad version se mapea usando <version>, - e Hibernate la incrementará automáticamente durante la limpieza si la entidad está sucia. - - - - Por supuesto, si estás operando un entorno de baja-concurrencia-de-datos y no requieres - chequeo de versiones, puedes usar este enfoque y simplemente saltar el chequeo de versiones. - En ese caso, el último compromiso (commit) gana será la estrategia por - defecto para tus transacciones de aplicación largas. Ten en mente que esto podría confundir - a los usuarios de la aplicación, pues podrían experimentar actualizaciones perdidas sin - mensajes de error ni chance de fusionar los cambios conflictivos. - - - - Claramente, el chequeo manual de versiones es factible solamente en circunstancias muy triviales, - y no es práctico para la mayoría de aplicaciones. Frecuentemente, no sólo intancias solas, sino grafos - completos de objetos modificados tienen que ser chequeados. Hibernate ofrece chequeo de versiones - automático con el paradigma de diseño de Session larga o de instancias separadas. - - - - - - Sesión larga y versionado automático - - - Una sola instancia de Session y sus instancias persistentes - son usadas para toda la transacción de aplicación. Hibernate chequea las versiones - de instancia en el momento de limpieza (flush), lanzando una excepción si se detecta - una modificación concurrente. Concierne al desarrollador capturar y manejar esta excepción - (las opciones comunes son la oportunidad del usuario de fusionar los cambios, o recomenzar el - proceso de negocio sin datos añejos). - - - - La Session se desconecta de cualquier conexión JDBC subyacente - al esperar por una interacción del usuario. Este enfoque es el más eficiente en términos - de acceso a base de datos. La aplicación no necesita tratar por sí misma con el chequeo de - versiones, ni re-uniendo instancias separadas, ni tiene que recargar instancias en cada - transacción de base de datos. - - - - - - El objeto foo todavía conoce en qué Session fue cargado. - Session.reconnect() obtiene una nueva conexión (o puedes proveer una) y - reasume la sesión. El método Session.disconnect() desconectará la sesión - de la conexión JDBC y la devolverá la conexión al pool (a menos que hayas provisto la conexión). - Después de la reconexión, para forzar un chequeo de versión en datos que no estés actualizando, - puedes llamar a Session.lock() con LockMode.READ sobre - cualquier objeto que pudiese haber sido actualizado por otra transacción. No necesitas bloquear - ningún dato que sí estés actualizando. - - - - Si las llamadas explícitas a disconnect() y reconnect() - son muy onerosas, puedes usar en cambio hibernate.connection.release_mode. - - - - Este patrón es problemático si la Session es demasiado grande para ser almacenada - durante el tiempo de pensar del usuario, por ejemplo, una HttpSession debe - mantenerse tan pequeña como sea posible. Ya que la Session es también el caché - (obligatorio) de primer nivel y contiene todos los objetos cargados, podemos probablemente cargar - esta estrategia sólo para unos pocos ciclos petición/respuesta. Esto está de hecho recomendado, ya que - la Session tendrá pronto también datos añejos. - - - - Nota también que debes mantener la Session desconectada próxima a la capa - de persistencia. En otras palabras, usa una sesión de EJB con estado para tener la - Session y no transferirla a la capa web para almacenarla en la - HttpSession (ni incluso serializarla a una capa separada). - - - - - - Objetos separados y versionado automático - - - Cada interacción con el almacén persistente ocurre en una nueva Session. - Sin embargo, las mismas instancias persistentes son reusadas para cada interacción con la base de - datos. La aplicación manipula el estado de las instancias separadas originalmente cargadas en otra - Session y luego las readjunta usando Session.update(), - Session.saveOrUpdate(), o Session.merge(). - - - - - - De nuevo, Hibernate chequeará las versiones de instancia durante la limpieza (flush), - lanzando una excepción si ocurrieron actualizaciones en conflicto. - - - - Puedes también llamar a lock() en vez de update() - y usar LockMode.READ (realizando un chequeo de versión, puenteando - todos los cachés) si estás seguro que el objeto no ha sido modificado. - - - - - - Personalizando el versionado automático - - - Puedes deshabilitar el incremento de versión automático de Hibernate para propiedades en particular - y colecciones estableciendo el atributo de mapeo optimistic-lock a - false. Hibernate entonces no incrementará ya más las versiones si la propiedad está - sucia. - - - - Los esquemas de base de datos heredados son frecuentemente estáticos y no pueden ser modificados. - U otras aplicaciones podrían también acceder la misma base de datos y no saber cómo manejar los números - de versión ni incluso timestamps. En ambos casos, el versionado no puede confiarse a una columna en - particular en una tabla. Para forzar un chequeo de versiones sin un mapeo de propiedad de versión o - timestamp, con una comparación del estado de todos los campos en una fila, activa - optimistic-lock="all" en el mapeo de <class>. - Nota que esto conceptualmente funciona solamente si Hibernate puede comparar el estado viejo y nuevo, - es decir, si usas una sola Session larga y no - sesión-por-petición-con-instancias-separadas. - - - - A veces las modificaciones concurrentes pueden permitirse, en cuanto los cambios que hayan sido - hechos no se traslapen. Si estableces optimistic-lock="dirty" al mapear la - <class>, Hibernate sólo comparará los campos sucios durante la limpieza. - - - - En ambos casos, con columnas de versión/timestamp dedicadas o con comparación de campos - completa/sucios, Hibernate usa una sola sentencia UPDATE - (con una cláusula WHERE apropiada) por entidad para ejecutar el chequeo - de versiones y actualizar la información. Si usas persistencia transitiva para la re-unión - en cascada de entidades asociadas, Hibernate podría ejecutar actualizaciones innecesarias. - Esto usualmente no es un problema, pero podrían ejecutarse disparadores (triggers) - on update en la base de datos incluso cuando no se haya hecho ningún cambio - a las instancias separadas. Puedes personalizar este comportamiento estableciendo - select-before-update="true" en el mapeo de <class>, - forzando a Hibernate a SELECT la instancia para asegurar que las actualizaciones - realmente ocurran, antes de actualizar la fila. - - - - - - - - Bloqueo pesimista - - - No se pretende que los usuarios gasten mucho tiempo preocupándose de las estrategias de bloqueo. - Usualmente es suficiente con especificar un nivel de aislamiento para las conexiones JDBC y entonces - simplemente dejar que la base de datos haga todo el trabajo. Sin embargo, los usuarios avanzados pueden - a veces obtener bloqueos exclusivos pesimistas, o reobtener bloqueos al comienzo de una nueva - transacción. - - - - ¡Hibernate siempre usará el mecanismo de bloqueo de la base de datos, nunca bloqueo - de objetos en memoria! - - - - La clase LockMode define los diferentes niveles de bloqueo que pueden ser adquiridos - por Hibernate. Un bloqueo se obtiene por los siguientes mecanismos: - - - - - - LockMode.WRITE se adquiere automáticamente cuando Hibernate actualiza o - inserta una fila. - - - - - LockMode.UPGRADE puede ser adquirido bajo petición explícita del usuario - usando SELECT ... FOR UPDATE en base de datos que soporten esa sintáxis. - - - - - LockMode.UPGRADE_NOWAIT puede ser adquirido bajo petición explícita del usuario - usando un SELECT ... FOR UPDATE NOWAIT bajo Oracle. - - - - - LockMode.READ es adquirido automáticamente cuando Hibernate lee datos - bajo los niveles de aislamiento Repeatable Read o Serializable. Puede ser readquirido por - pedido explícito del usuario. - - - - - LockMode.NONE representa la ausencia de un bloqueo. Todos los objetos se pasan - a este modo de bloqueo al final de una Transaction. Los objetos asociados con una - sesión vía una llamada a update() o saveOrUpdate() también - comienzan en este modo de bloqueo. - - - - - - La "petición explícita del usuario" se expresa en una de las siguientes formas: - - - - - - Una llamada a Session.load(), especificando un LockMode. - - - - - Una llamada a Session.lock(). - - - - - Una llamada a Query.setLockMode(). - - - - - - Si se llama a Session.load() con UPGRADE o - UPGRADE_NOWAIT, y el objeto pedido no ha sido aún cargado por la sesión, el objeto es - cargado usando SELECT ... FOR UPDATE. Si se llama a load() para - un objeto que ya esté cargado con un bloqueo menos restrictivo que el pedido, Hibernate llama a - lock() para ese objeto. - - - - Session.lock() realiza un chequeo de número de versión si el modo de bloqueo especificado - es READ, UPGRADE o UPGRADE_NOWAIT. (En el caso de - UPGRADE o UPGRADE_NOWAIT, se usa - SELECT ... FOR UPDATE.) - - - - Si la base de datos no soporta el modo de bloqueo solicitado, Hibernate usará un modo alternativo - apropiado (en vez de lanzar una excepción). Esto asegura que las aplicaciones serán portables. - - - - - - diff --git a/documentation/manual/es-ES/src/main/docbook/modules/tutorial.xml b/documentation/manual/es-ES/src/main/docbook/modules/tutorial.xml deleted file mode 100644 index 99dfb74997..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/tutorial.xml +++ /dev/null @@ -1,1270 +0,0 @@ - - Introducción a Hibernate - - - Prefacio - - - Este capítulo es un tutorial introductorio de Hibernate. Comenzamos con - una aplicación simple de línea de comandos usando un base de datos - en-memoria y desarrollándola en fácil para entender los pasos. - - - - Este tutorial está concebido para usuarios nuevos de Hibernate pero - requiere conocimiento en Java y SQL. Está basado en un tutorial de - Michael Gloegl. Las bibliotecas de terceros que mencionamos son para JDK 1.4 - y 5.0. Podrías necesitar otras para JDK 1.3. - - - - - - Parte 1 - La primera Aplicación Hibernate - - - Primero, crearemos una aplicación simple de Hibenate basada en consola. - Usamos usamos una base de datos en-memoria (HSQL DB), de modo que no necesitamos - instalar ningún servidor de base de datos. - - - - Asumamos que necesitamos una aplicación pequeña de base de datos que - pueda almacenar eventos que queremos atender, e información acerca de los - hostales de estos eventos. - - - - La primera cosa que hacemos, es armar nuestro directorio de desarrollo y poner - en él todas las bibliotecas Java que necesitamos. Descarga la distribución - de Hibernate del sitio web de Hibernate. Extrae el paquete y coloca todas las - bibliotecas requeridas encontradas en /lib dentro del directorio - /lib de nuestro nuevo directorio de desarrollo de trabajo. - Debe asemejarse a esto: - - - - - - Este es el conjunto mínimo de bibliotecas requeridas para Hibernate (observa que - también hemos copiado hibernate3.jar, el fichero principal). Ver el fichero - README.txt en el directorio lib/ de la distribución - de Hibernate para más información sobre bibliotecas de terceros requeridas y - opcionales. (Realmente, Log4J no es requerida aunque preferida por muchos desarrolladores). - - - - Por siguiente, creamos una clase que represente el evento que queremos - almacenar en base de datos. - - - - La primera clase - - - Nuestra primera clase persistente es un JavaBean simple con algunas propiedades: - - - - - - Puedes ver que esta clase usa las convenciones de nombrado estándar de JavaBean - para métodos getter y setter de propiedad, así como visibilidad privada - para los campos. Esto es un diseño recomendado, aunque no requerido. Hibernate - también puede acceder a los campos directamente; el beneficio de los métodos - de acceso es la robustez para la refactorización. - - - - La propiedad id tiene un valor único de identificador para - un evento en particular. Todas las clase de entidad persistentes ( también hay - clases dependientes menos importantes) necesitarán una propiedad identificadora - similar si queremos usar el conjunto completo de funcionalidades de Hibernate. De hecho, - la mayoría de las aplicaciones (esp. aplicaciones web) necesitan distinguir - objetos por identificador, de modo que debes considerar esto como un aspecto en vez de una - limitación. Sin embargo, usualmente no manipulamos la identidad de un objeto, por - lo tanto el método setter debe ser privado. Sólo Hibernate asignará - identificadores cuando un objeto sea salvado. Puedes ver que Hibernate puede acceder a - métodos de acceso públicos, privados y protegidos, tanto como directamente a - campos (públicos, privados y protegidos). La elección está en ti, - y puedes ajustarla a tu diseño de aplicación. - - - - El constructor sin argumentos es un requerimiento para todas las clases persistentes. - Hibernate tiene que crear objetos para ti, usando reflección Java. El constructor - puede ser privado, sin embargo, la visibilidad de paquete es requerida para la generación - de proxies en tiempo de ejecución y la recuperación de datos sin - instrumentación del bytecode. - - - - Coloca este fichero de código Java en un directorio llamado src - en la carpeta de desarrollo. El directorio ahora debe verse como esto: - - - -+src - Event.java]]> - - - En el próximo paso, le decimos a Hibernate sobre esta clase persistente. - - - - - - El fichero de mapeo - - - Hibernate necesita saber cómo cargar y almacenar objetos de la - clase persistente. Aquí es donde el fichero de mapeo de Hibernate - entra en juego. El fichero de mapeo le dice a Hibernate a qué tabla en - la base de datos tiene que acceder, y qué columnas en esta tabla debe usar. - - - - La estructura básica de un fichero de mapeo se parece a esto: - - - - - - -[...] -]]> - - - Observa que el DTD de Hibernate es muy sofisticado. Puedes usarlo para - autocompleción de los elementos y atributos XML de mapeo en tu - editor o IDE. Debes también abrir el fichero DTD en tu editor de - texto. Es la forma más fácil para tener un panorama de todos - los elementos y atributos y ver los valores por defectos, así como - algunos comentarios. Nota que Hibernate no cargará el fichero DTD de - la web, sino que primero buscará en el classpath de la aplicación. - El fichero DTD está incluído en hibernate3.jar - así como también en el directorio src/ de la - distribución de Hibernate. - - - - Omitiremos la declaración de DTD en futuros ejemplos para acortar - el código. Por supuesto, no es opcional. - - - - Entre las dos etiquetas hibernate-mapping, incluye - un elemento class. Todas las clases de entidad - persistentes (de nuevo, podría haber más adelante clases - dependientes, que no sean entidades de-primera-clase) necesitan dicho mapeo - a una tabla en la base de datos SQL: - - - - - - - - -]]> - - - Hasta ahora dijimos a Hibernate cómo persistir y cargar el objeto - de clase Event a la tabla EVENTS, - cada instancia representada por una fila en esta tabla. Ahora continuamos con - un mapeo de la propiedad de identificado único a la clave primaria - de la tabla. Además, como no queremos cuidar del manejo de este identificador, - configuramos la estrategia de generación de identificadores para una columna - clave primaria delegada: - - - - - - - - - - -]]> - - - El elemento id el la declaración de la propiedad - identificadora, name="id" declara el nombre de la - propiedad Java. Hibernate usará los métodos getter y setter - para acceder a la propiedad. El attributo de columna dice a Hibernate cuál - columna de la tabla EVENTS usamos para esta clave primaria. - El elemento anidado generator especifica la estrategia de - generación de identificadores, en este caso usamos increment, - que es un método muy simple de incremento de número en-memoria - útil mayormente para testeo (y tutoriales). Hibernate también - soporta identificadores generados por base de datos, globalmente únicos, - así como también asignados por aplicación (o cualquier - estrategia para la que hayas escrito una extensión). - - - - Finalmente incluímos declaraciones para las propiedades persistentes - de la clases en el fichero de mapeo. Por defecto, ninguna propiedad de la clase - se considera persistente: - - - - - - - - - - - - -]]> - - - Al igual que con el elemento id, el atributo name - del elemento property dice a Hibernate cáles métodos - getter y setter usar. - - - - ¿Por qué el mapeo de la propiedad date - incluye el atributo column, pero el de la de - title no? Sin el atributo column - Hibernate usa por defecto el nombre de propiedad como nombre de columna. - Esto funciona bien para title. Sin embargo, - However, date es una palabra reservada en la - mayoría de las bases de datos, así que mejor la mapeamos - a un nombre diferente. - - - - La próxima cosa interesante es que el mapeo de title - carece de un atributo type. Los tipos que declaramos y usamos - en el fichero de mapeo no son, como podrías esperar, tipos de datos Java. - Tampoco son tipos de base de datos SQL. Estos tipos son los llamados así - Tipos de mapeo de Hibernate, convertidores que pueden - traducir de tipos Java a SQL y vice versa. De nuevo, Hibernate intentará - determinar la conversión y el mapeo mismo de tipo correctos si el atributo - type no estuviese presente en el mapeo. En algunos casos esta - detección automática (usando reflección en la clase Java) - puede no tener lo que esperas o necesitas. Este es el caso de la propiedad - date. Hibernate no puede saber is la propiedad mapeará - a una columna date, timestamp o - time. Declaramos que queremos preservar la información - completa de fecha y hora mapeando la propiedad con un timestamp. - - - - Este fichero de mapeo debe ser salvado como Event.hbm.xml, - justo en el directorio próximo al fichero de código fuente de - la clase Java Event. El nombrado de los ficheros de mapeo - puede ser arbitrario, sin embargo, el sufijo hbm.xml se ha - vuelto una convención el la comunidad de desarrolladores de Hibernate. - La estructura de directorio debe ahora verse como esto: - - - -+src - Event.java - Event.hbm.xml]]> - - - Continuamos con la configuración principal de Hibernate. - - - - - - Configuración de Hibernate - - - Tenemos ahora una clase persistente y su fichero de mapeo en su sitio. Es momento de - configurar Hibernate. Antes que hagamos esto, necesitaremos una base de datos. - HSQL DB, un DBMS SQL en-memoria basado en Java, puede ser descargado del sitio web - de HSQL DB. Realmente, de esta descarga sólo necesitas el hsqldb.jar. - Coloca este fichero en el directorio lib/ de la carpeta de desarrollo. - - - - Crea un directorio llamado data en la raíz del directorio de - desarrollo. Allí es donde HSQL DB almacenará sus ficheros de datos. - - - - Hibernate es la capa en tu aplicación que se conecta a esta base de datos, - de modo que necesita información de conexión. Las conexiones se hacen - a través de un pool de conexiones JDBC, que tambén tenemos que configurar. - La distribución de Hibernate contiene muchas herramientas de pooling de conexiones - JDBC de código abierto, pero para este tutorial usaremos el pool de conexiones - prefabricado dentro de Hibernate. Observa que tienes que copiar la biblioteca requerida - en tu classpath y usar diferentes configuraciones de pooling de conexiones si quieres - usar un software de pooling JDBC de terceros de calidad de producción. - - - - Para la configuración de Hibernate, podemos usar un fichero - hibernate.properties simple, un fichero hibernate.cfg.xml - ligeramente más sofisticado, o incluso una configuración completamente - programática. La mayoría de los usuarios prefieren el fichero de - configuración XML: - - - - - - - - - - - org.hsqldb.jdbcDriver - jdbc:hsqldb:data/tutorial - sa - - - - 1 - - - org.hibernate.dialect.HSQLDialect - - - true - - - create - - - - - -]]> - - - Observa que esta configuración XML usa un DTD diferente. - Configuramos la SessionFactory de Hibernate, una - fábrica global responsable de una base de datos en particular. - Si tienes varias bases de datos, usa varias configuraciones - <session-factory> , usualmente en varios - ficheros de configuración (para un arranque más fácil). - - - - Los primeros cuatro elementos property contienen la configuración - necesaria para la conexión JDBC. El elemento de dialecto property - especifica la variante de SQL en particular que genera Hibernate. La opción - hbm2ddl.auto activa la generación automática de esquemas - de base de datos, directamente en la base de datos. Esto, por supuesto, puede desactivarse - (quitando la opción config) o redirigido a un fichero con la ayuda de la tarea - de Ant SchemaExport. Finalmente, agregamos el(los) fichero(s) de mapeo - para clases persistentes. - - - - Copia este fichero dentro del directorio de código fuente, de modo que - termine ubicado en la raiíz del classpath. Hibernate busca automáticamente - un fichero llamado hibernate.cfg.xml en la raíz del classpath - al arrancar. - - - - - - Construyendo con Ant - - - Construiremos ahora el tutorial con Ant. Necesitarás tener Ant instalado. - Obténlo de Página - de descarga de Ant. No se cubrirá aquí cómo instalar Ant. - Por favor refiérete al - Manual de Ant. Después que hayas instalado Ant, podemos comenzar a - crear el buildfile. Será llamado build.xml y colocado - directamente en el directorio de desarrollo. - - - - Reparar Ant - - Observa que la distribución de Ant está por defecto rota - (como se describe en el FAQ de Ant) y tiene que ser reparado por ti, - por ejemplo, si quisieras usar JUnit desde dentro de tu fichero de construcción. - Para hacer que funcione la tarea de JUnit (no lo necesitaremos en este tutorial), - copia junit.jar a ANT_HOME/lib o quita el trozo de plugin - ANT_HOME/lib/ant-junit.jar. - - - - - Un fichero de construcción básico se ve como esto: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Esto dirá a Ant que agregue todos los ficheros en el directorio lib que terminen con - .jar al classpath usado para la compilación. También copiará - todos los ficheros que no sean código Java al directorio objetivo, por ejemplo, - ficheros de configuración y mapeos de Hibernate. Si ahora corres Ant, debes obtener - esta salida: - - - ant -Buildfile: build.xml - -copy-resources: - [copy] Copying 2 files to C:\hibernateTutorial\bin - -compile: - [javac] Compiling 1 source file to C:\hibernateTutorial\bin - -BUILD SUCCESSFUL -Total time: 1 second ]]> - - - - - Arranque y ayudantes - - - Es momento de cargar y almacenar algunos objetos Event, - pero primero tenemos que completar la configuración de algún - código de infraestructura. Tenemos que arrancar Hibernate. Este - arranque incluye construir un objeto SessionFactory global - y almacenarlo en algún sitio de fácil acceso en el código - de aplicación. Una SessionFactory puede abrir nuevas - Session's. Una Session representa un unidad - de trabajo mono-hebra. La SessionFactory es un objeto global - seguro entre hebras, instanciado una sola vez. - - - - Crearemos una clase de ayuda HibernateUtil que cuide del - arranque y haga conveniente el manejo de Session. - El así llamado patrón Sesión de Hebra Local - (ThreadLocal Session) es útil aquí; mantenemos la unidad - de trabajo actual asociada a la hebra actual. Echemos una mirada a la implementación: - - - - - - Esta clase no ólo produce la SessionFactory global en - su inicializador static (llamado sólo una vez por la JVM al cargar la clase), - sino que también tiene una variable ThreadLocal para - tener la Session para la hebra actual. No importa cuándo - llames a HibernateUtil.currentSession(), siempre devolverá - la misma unidad de trabajo de Hibernate en la misma hebra. Una llamada a - HibernateUtil.closeSession() termina la unidad de trabajo actualmente - asociada a la hebra. - - - - Asegúrate de entender el concepto Java de una variable local a una hebra antes - de usar esta ayuda. Una clase HibernateUtil más potente puede - encontrarse en CaveatEmptor, http://caveatemptor.hibernate.org/, - así como en el libro "Java Persistence with Hibernate". Observa que esta clase no es necesaria - si despliegas Hibernate en un servidor de aplicaciones J2EE: una Session - será automáticamente ligada a la transacción JTA actual, y puedes - buscar la SessionFactory a través de JNDI. Si usas JBoss AS, - Hibernate puede ser desplegado como un servicio de sistema manejado y automáticamente - ligará la SessionFactory a un nombre JNDI. - - - - Coloca HibernateUtil.java en el directorio de fuentes de desarrollo, - junto a Event.java: - - - -+src - Event.java - Event.hbm.xml - HibernateUtil.java - hibernate.cfg.xml -+data -build.xml]]> - - - Esto también debe compilar sin problemas. Finalmente necesitamos configurar - un sistema de logging (registro). Hibernate usa commons logging y te deja la elección - entre Log4J y logging de JDK 1.4. La mayoría de los desarrolladores prefieren - Log4J: copia log4j.properties de la distribución de Hibernate - (está en el directorio etc/) a tu directorio src, - junto a hibernate.cfg.xml. Echa una mirada a la configuración de - ejemplo y cambia los ajustes si te gusta tener una salida más verborrágica. - Por defecto, sólo se muestra el mensaje de arranque de Hibernate en la salida. - - - - La infraestructura del tutorial está completa, y estamos listos para hacer - algún trabajo real con Hibernate. - - - - - - Cargando y almacenando objetos - - - Finalmente, podemos usar Hibernate para cargar y almacenar objetos. - Escribimos una clase EventManager con un método - main(): - - - - - - Leemos algunos argumentos de la línea de comandos, y si el primer - argumento es "store", creamos y almacenamos un nuevo Event: - - - - - - Creamos un nuevo objeto Event, y se lo damos a Hibernate. - Hibernate cuida ahora del SQL y ejecuta INSERTs en la base - de datos. Echemos una mirada al código de manejo de Session - y Transaction antes de ejecutar esto. - - - - Una Session es una sola unidad de trabajo. Podría sorprenderte - que tengamos una API adicional, Transaction. Esto implica que una unidad - de trabajo puede ser "más larga" que una sola transacción de base de datos; - imagina una unidad de trabajo que se abarca varios ciclos petición/respuesta HTTP - (por ejemplo, un diálogo asistente) en una aplicación web. Separar las - transacciones de base de datos de "las unidades de trabajo de la aplicación desde - el punto de vista del usuario" es uno de los conceptos básicos de diseño de - Hibernate. Llamamos una unidad de trabajo larga Transacción de - Aplicación, usualmente encapsulando varias transacciones de base de - datos más cortas. Por ahora mantendremos las cosas simples y asumiremos una - granularidad uno-a-uno entre una Session y una Transaction. - - - - ¿Qué es lo que hacen Transaction.begin() y commit()? - ¿Dónde está el rollback en caso que algo vaya mal? La API de Transaction - de Hibernate es opcional realmente, pero la usamos por conveniencia y portabilidad. Si manejases - la transacción de base de datos por ti mismo (por ejemplo, llamando a - session.connection.commit()), ligarías el código a un entorno - de despliegue particular, en este JDBC directo no manejado. Estableciendo la fábrica - de Transaction en tu configuración de Hibernate puedes desplegar - tu capa de persistencia en cualquier sitio. Echa una mirada al - para más información sobre manejo y demarcación de transacciones. - Hemos saltado también cualquier manejo de excepciones y rollback en este ejemplo. - - - - Para ejecutar la primera rutina tenemos que agregar un objetivo llamable al fichero - de construcción de Ant: - - - - - - - -]]> - - - El valor del argumento action es establecido por línea de - comandos al llamar al objetivo: - - - ant run -Daction=store]]> - - - Debes ver, después de la compilación, a Hibernate arrancando y, dependiendo - de tu configuración mucha salida de registro (log). Al final encontrarás - la siguiente línea: - - - - - - Esta es la INSERT ejecutada por Hibernate, los signos de preguntas - representan parámetros de ligado JDBC. Para ver los valores ligados como - argumentos, o para reducir la verborragia del registro, chequea tu - log4j.properties. - - - - Ahora quisiéramos listar acontecimientos almacenados también, - así que agregamos una opción al método principal: - - - - - - Agregamos también un nuevo método listEvents(): - - - - - - Lo que hacemos aquí es usar una consulta HQL (Lenguaje de Consulta de Hibernate - o Hibernate Query Language) para cargar todos los objetos Event - existentes de la base de datos. Hibernate generará el SQL apropiado, lo enviará - a la base de datosy poblará los objetos Event con datos. - Puedes, por supuesto, crear consultas más complejas con HQL. - - - - Si ahora llamas a Ant con -Daction=list, debes ver los eventos - que has almacenado hasta ahora. Puede sorprenderte que esto no funcione, al menos - si has seguido este tutorial paso por paso; el resultado siempre estará - vacío. La razon de esto es la opción hbm2ddl.auto - en la configuración de Hibernate: Hibernate recreará la base de datos - en cada ejecución. Deshabilítala quitando la opción, y verás - resultados en tu listado después que llames a la acción store - unas cuantas veces. La generación y exportación de esquema es útil - mayormente en testeo unitario. - - - - - - - - Part 2 - Mapeando asociaciones - - - Hemos mapeado un clase de entidad persistente a una tabla. Construyamos sobre esto y agreguemos - algunas asociaciones de clase. Primero agregaremos personas a nuestra aplicación, - y almacenaremos una lista de eventos en las que participan. - - - - Mapeando la clase Person - - - El primer corte de la clase Person es simple: - - - - - - Crea un fichero de mapeo llamado Person.hbm.xml: - - - - - - - - - - - - - -]]> - - - Finalmente, agrega el nuevo mapeo a la configuración de Hibernate: - - - - -]]> - - - Crearemos ahora una asociación entre estas dos entidades. Obviamente, - las personas pueden participar en eventos, y los eventos tienen participantes. - Las cuestiones de diseño con que tenemos que tratar son: direccionalidad, - multiplicidad y comportamiento de colección. - - - - - - Una asociación unidireccional basada en Set - - - Agregaremos una colección de eventos a la clase Person. - De esta forma podemos navegar facilmente a los eventos de una persona en particular, - sin ejecutar una consulta explícita, llamando a aPerson.getEvents(). - Usamos una colección Java, un Set, porque la colección no - contendrá elementos duplicados y el ordenamiento no nos es relevante. - - - - Hasta ahora hemos diseñado asociaciones unidireccionales multivaluadas, implementadas con un - Set. Escribamos el código para esto en las clases Java y luego lo - mapeemos: - - - - - - Antes que mapeemos esta asociación, piensa sobre el otro lado. Claramente, podemos - mantener esto solamente unidireccional. O podemos crear otra colección en el - Event, si queremos ser capaces de navegarlos bidireccionalmente; - por ejemplo, anEvent.getParticipants(). Esta es una elección - de diseño que recae en ti, pero lo que está claro de esta discusión - es la multiplicidad de la asociación: "multi" valuada a ambos lados, llamamos a esto - una asociación muchos-a-muchos. Por lo tanto, usamos un mapeo - many-to-many de Hibernate: - - - - - - - - - - - - - - - -]]> - - - Hibernate soporta todo tipo de mapeos de colección, siendo el más común - un <set>. Para una asociación muchos-a-muchos (o relación - de entidad n:m), se necesita una tabla de asociación. Cada fila en esta - tabla representa un enlace entre una persona y un evento. Esta tabla se configura con el atributo - table del elemento set. El nombre de la columna identificadora - en la asociación, para el 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 del <many-to-many>. También tienes que decirle - a Hibernate la clase de los objetos en tu colección (correcto: la clase del otro lado de la - colección de referencias). - - - - El esquema de base de datos para este mapeo es, por lo tanto: - - - | *EVENT_ID | | | - | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | - | TITLE | |__________________| | AGE | - |_____________| | FIRSTNAME | - | LASTNAME | - |_____________| - ]]> - - - - - Trabajando la asociación - - - Traigamos alguna gente y eventos juntos en un nuevo método en - EventManager: - - - - - - Después de cargar una Person y un Event, simplemente - modifica la colección usando sus métodos normales. Como puedes ver, no hay una llamada - explícita a update() o save(). Hibernate detecta - automáticamente que la colección ha sido modificada y necesita ser salvada. Esto - es llamado chequeo sucio automótico (automatic dirty checking), y - también puedes intentarlo modificando el nombre de la propiedad de fecha de cualquiera de tus - objetos. Mientras estén en estado persistente, esto es, ligados a una - Session de Hibernate particular (es decir, justo han sido cargados o almacenados - en una unidad de trabajo), Hibernate monitoriza cualquier cambio y ejecuta SQL en estilo - escribe-por-detrás. El proceso de sincronización del estado de memoria con la base - de datos, usualmente sólo al final de una unidad de trabajo, - es llamado limpieza (flushing). - - - - Podrías, por supuesto, cargar persona y evento en unidades de trabajo diferentes. O - modificas un objeto fuera de una Session, cuando no está en estado - persistente (si antes era persistente llamamos a este estado separado (detached) - ). En código (no muy realista), esto se vería como sigue: - - - - - - La llamada a update hace a un objeto persistente de nuevo, podrías - decir que la liga a una nueva unidad de trabajo, de modo que cualquier modificación que - le hagas mientras esté separado puede ser salvada a base de datos. - - - - Bueno, esto no es muy usado en nuestra situación actual, pero es un concepto - importante que puedes diseñar en tu propia aplicación. Por ahora, completa - este ejercicio agregando una nueva acción al método main de - EventManager y llámala desde la línea de comandos. - Si necesitas los identificadores de una persona o evento, el método - save() los devuelve. - - - - Esto fue un ejemplo de una asociación entre dos clases igualmente importantes, dos entidades. - Como se ha mencionado anteriormente, hay otras clases y tipos en un modelo típico, - usualmente "menos importantes". Algunos ya los habrás visto, como un int - o un String. Llamamos a estas clases tipos de valor (value types), - 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 tuvieran el mismo primer nombre). Por supuesto, - los tipos de valor no sólo pueden encontrarse en el JDK (de hecho, en una aplicación - Hibernate todas las clases del JDK son consideradas tipos de valor), sino que además puedes - escribir por ti mismo clases dependientes, por ejemplo, Address o - MonetaryAmount. - - - - También puedes diseñar una colección de tipos de valor. Esto es conceptualmente - muy diferente de una colección de referencias a otras entidades, pero se ve casi lo mismo en - Java. - - - - - - Colección de valores - - - Agregamos una colección de objetos tipificados en valor a la entidad Person. - Queremos almacenar direcciones de email, de modo que el tipo que usamos es String, - y la colección es nuevamente un Set: - - - - - El mapeo de este Set: - - - - - -]]> - - - La diferencia comparada con el mapeo anterior es la parte element, que le dice - a Hibernate que la colección no contiene referencias a otra entidad, sino una colección - de elementos de tipo String (el nombre en minúsculas te dice que es un - tipo/conversor de mapeo de Hibernate). Una vez más, el atributo table del - elemento set determina el nombre de la tabla para la colección. El elemento - key define el nombre de la columna clave foránea en la tabla de colección. - El atributo column en el elemento element define el nombre de - columna donde realmente serán almacenados los valores String. - - - - Echa una mirada al esquema actualizado: - - - | *EVENT_ID | | | |___________________| - | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID | - | TITLE | |__________________| | AGE | | *EMAIL_ADDR | - |_____________| | FIRSTNAME | |___________________| - | LASTNAME | - |_____________| - ]]> - - - Puedes ver que la clave primaria de la tabla de colección es de hecho una clave - compuesta, usando ambas columnas. Esto implica también que no pueden haber - direcciones de email duplicadas por persona, que es exactamente la semántica - que necesitamos para un conjunto en Java. - - - - Puedes ahora intentar y agregar elementos a esta colección, al igual que - hicimos antes enlazando personas y eventos. Es el mismo código en Java. - - - - - - Asociaciones bidireccionales - - - A continuacion vamos a mapear una asociación bidireccional, haciendo que la - asociación entre persona y evento funcione desde ambos lados en Java. Por supuesto, - el esquema de base de datos no cambia; todavía necesitamos multiplicidad muchos-a-muchos. - Una base de datos relacional es más flexible que un lenguaje de programación - de red, así que no necesita nada parecido a una dirección de navegación; - los datos pueden ser vistos y recuperados en cualquier forma posible. - - - - Primero agrega una colección de participantes a la clase de eventos - Event: - - - - - - Ahora mapea este lado de la asociación también, en - Event.hbm.xml. - - - - - -]]> - - - Como ves, estos son mapeos normales de set en ambos documentos de - mapeo. Nota que los nombres de columnas en key y - many-to-many fueron permutados en ambos documentos de mapeo. Aquí la - adición más importante es el atributo inverse="true" en el - elemento set del mapeo de colección de Event. - - - - Lo que esto significa es que Hibernate debe tomar el otro lado - la clase Person - - cuando necesite descubrir información sobre el enlace entre las dos. Esto será mucho - más fácil de entender una vez que veas cómo se crea el enlace bidireccional - entre nuestras dos entidades. - - - - - - Trabajando enlaces bidireccionales - - - Primero, ten en mente que Hhibernate no afecta la semántica normal de Java. ¿Cómo - hemos creado un enlace entre una Person y un Event en el - ejemplo unidireccional? Hemos agregado una instancia de Event a la colección - de referencias de eventos de una instancia de Person. De modo que, obviamente, - si queremos que este enlace funcione bidireccionalmente, tenemos que hacer lo mismo del otro lado, - agregando una referencia a Person a la colección en un Event. - Este "establecer el enlace a ambos lados" es absolutamente necesario y nunca debes olvidar hacerlo. - - - - Muchos desarrolladores programan a la defensiva y crean métodos de - manejo de un enlace para establecer correctamente ambos lados, por ejemplo - en Person: - - - - - - Nota que los métodos get y set para esta colección son ahora protegidos. Esto le - permite a clases en el mismo paquete y a subclases acceder aún a los métodos, pero - previene a cualquier otro de ensuciarse con la colección directamente (bueno, casi). - Probablemente debas hacer lo mismo con la colección al otro lado. - - - - Y ¿qué del atributo de mapeo inverse? Para ti, y para Java, un enlace - bidireccional es simplemente cuestión de establecer correctamente las referencias a ambos - lados. Hibernate, sin embargo, no tiene suficiente información para arreglar correctamente - sentencias INSERT y UPDATE de SQL (para evitar violación - de restricciones), y necesita alguna ayuda para manejar asociaciones bidireccionales apropiadamente. - El hacer un lado de la asociación inverse le dice a Hibernate que basicamente - lo ignore, que lo considere un espejo del otro lado. Esto es todo lo necesario para - que Hibernate resuelva todas las incidencias al transformar un modelo de navegación direccional a - un esquema SQL de base de datos. Las reglas que tienes que recordar son directas: Todas las asociaciones - bidireccionales necesitan uno de los lados como inverse. En una asociación - uno-a-muchos debe ser el lado-de-muchos. En una asociación muchos-a-muchos, puedes tomar cualquier - lado, no hay diferencia. - - - - - - - Summary - - - Este tutorial cubrió los fundamentos de escribir una simple aplicación independiente - de Hibernate. - - - - Si ya te sientes confidente con Hibernate, continúa navegando a través de la - tabla de contenidos de la documentación de referencia para los temas que encuentres - interesantes. Los más consultados son procesamiento transaccional (), - rendimiento de recuperación (), o el uso de la API - () y las funcionalidades de consulta (). - - - - No olvides chequear el sitio web de Hibernate por más (especializados) tutoriales. - - - - - \ No newline at end of file diff --git a/documentation/manual/es-ES/src/main/docbook/modules/xml.xml b/documentation/manual/es-ES/src/main/docbook/modules/xml.xml deleted file mode 100644 index 486ca3ca7e..0000000000 --- a/documentation/manual/es-ES/src/main/docbook/modules/xml.xml +++ /dev/null @@ -1,282 +0,0 @@ - - Mapeo XML - - - Nota que esta es una funcionalidad experimental en Hibernate 3.0 y está - bajo un desarrollo extremadamente activo. - - - - Trabajando con datos XML - - - Hibernate te permite trabajar con datos XML persistentes en casi la misma forma - que trabajas con POJOs persistentes. Un árbol XML analizado (parsed) puede ser - pensado como sólo otra forma de representar los datos relacionales a nivel de objetos, - en vez de POJOs. - - - - Hibernate soporta dom4j como API para manipular árboles XML. Puedes escribir - consultas que traigan árboles dom4j de la base de datos y tener cualquier modificación - que hagas al árbol sincronizada automáticamente a la base de datos. Puedes incluso tomar - un documento XML, analizarlo usando dom4j, y escribirlo a la base de datos con cualquiera - de las operaciones básicas de Hibernate: persist(), saveOrUpdate(), merge(), - delete(), replicate() (la fusión no está aún soportada). - - - - Esta funcionalidad tiene muchas aplicaciones incluyendo la importación/exportación de datos, - externalización de datos de entidad vía JMS o SOAP y reportes basados en XSLT. - - - - Un solo mapeo puede ser usado para mapear simultáneamente las propiedades de una clase y los nodos de un - documento XML a la base de datos, o, si no hay ninguna clase a mapear, puede ser usado para mapear sólo - el XML. - - - - Especificando los mapeos de XML y de clase juntos - - - He aquí un ejemplo de mapear un POJO y XML simultáneamente: - - - - - - - - - - - ... - -]]> - - - - Especificando sólo un mapeo XML - - - He aquí un ejemplo donde no hay ninguna clase POJO: - - - - - - - - - - - ... - -]]> - - - Este mapeo te permite acceder a los datos como un árbol dom4j, o como un grafo de pares nombre/valor de - propiedad (Maps de Java). Los nombres de propiedades son construcciones puramente - lógicas a las que se puede hacer referencia en consultas HQL. - - - - - - - - Mapeo de metadatos XML - - - Muchos elementos de mapeo de Hibernate aceptan el atributo node. Esto te permite espcificar - el nombre de un atributo o elemento XML que contenga los datos de la propiedad o entidad. El formato del - atributo node debe ser uno de los siguientes: - - - - - "element-name" - mapea al elemento XML mencionado - - - "@attribute-name" - mapea al atributo XML mencionado - - - "." - mapea al elemento padre - - - - "element-name/@attribute-name" - - mapea al atributo mencionado del elemento mencionado - - - - - - Para las colecciones y asociaciones monovaluadas, existe un atributo adicional embed-xml. - Si embed-xml="true", que es el valor por defecto, el árbol XML para la entidad - asociada (o colección de tipo de valor) será embebida directamente en el árbol XML para la entidad que - posee la asociación. En otro caso, si embed-xml="false", sólo el valor identificador - referenciado aparecerá en el XML para asociaciones de punto único y para las colecciones simplemente - no aparecerá en absoluto. - - - - ¡Debes ser cuidadoso de no dejar embed-xml="true" para demasiadas asociaciones, - ya que XML no trata bien la circularidad! - - - - - - - - - - - - - - - - - - - ... - -]]> - - - en este caso, hemos decidido embeber la colección de ids de cuenta, pero no los datos reales de cuenta. - La siguiente consulta HQL: - - - - - - devolvería conjuntos de datos como estos: - - - - 987632567 - 985612323 - - Gavin - A - King - - ... -]]> - - - Si estableces embed-xml="true" en el mapeo <one-to-many>, los datos - podrían verse así: - - - - - - 100.29 - - - - -2370.34 - - - Gavin - A - King - - ... -]]> - - - - - - Manipulando datos XML - - - Vamos a releer y actualizar documentos XML en la aplicación. Hacemos esto obteniendo una sesión dom4j: - - - - - - - - Es extremadamente útil combinar esta funcionalidad con la operación replicate() - de Hibernate para implementar la importación/exportación de datos basada en XML. - - - - - -