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.Batcher 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.