Hibernate.org Community Documentation

- Anterior
- Siguiente

## Capítulo 3. Configuración

Hibernate está diseñado para operar en muchos entornos diferentes y por lo tanto hay un gran número de parámetros de configuración. Afortunadamente, la mayoría tiene valores predeterminados sensibles y Hibernate se distribuye con un archivo `hibernate.properties` de ejemplo en `etc/` que muestra las diversas opciones. Simplemente ponga el fichero de ejemplo en su ruta de clase y personalícelo de acuerdo a sus necesidades.

## 3.1. 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 `org.hibernate.cfg.Configuration` se utiliza para construir una `org.hibernate.SessionFactory` inmutable. Los mapeos se compilan desde varios archivos de mapeo XML.

Puede obtener una instancia de `org.hibernate.cfg.Configuration` instanciándola directamente y especificando los documentos de mapeo XML. Si los archivos de mapeo están en la ruta de clase, utilice `addResource()`. Por ejemplo:

    Configuration cfg = new Configuration()

        .addResource("Item.hbm.xml")

        .addResource("Bid.hbm.xml");

Una manera opcional es especificar la clase mapeada y dejar que Hibernate encuentre el documento de mapeo por usted:

    Configuration cfg = new Configuration()

        .addClass(org.hibernate.auction.Item.class)

        .addClass(org.hibernate.auction.Bid.class);

Luego Hibernate buscará los archivos de mapeo llamados `/org/hibernate/auction/Item.hbm.xml` y `/org/hibernate/auction/Bid.hbm.xml` en la ruta de clase. Este enfoque elimina cualquier nombre de archivo establecido manualmente.

Una `org.hibernate.cfg.Configuration` también le permite especificar las propiedades de configuración. Por ejemplo:

    Configuration cfg = new Configuration()

        .addClass(org.hibernate.auction.Item.class)

        .addClass(org.hibernate.auction.Bid.class)

        .setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")

        .setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")

        .setProperty("hibernate.order_updates", "true");

Esta no es la única manera de pasar propiedades de configuración a Hibernate. Algunas opciones incluyen:

1. Pasar una instancia de `java.util.Properties` a `Configuration.setProperties()`.

2. Colocar un archivo llamado `hibernate.properties` en un directorio raíz de la ruta de clase.

3. Establecer propiedades `System` utilizando `java -Dproperty=value`.

4. Incluir los elementos `<property>` en `hibernate.cfg.xml` (esto se discute más adelante).

Si quiere empezar rápidamente `hibernate.properties` es el enfoque más fácil.

La `org.hibernate.cfg.Configuration` está concebida como un objeto de tiempo de inicio que se va a descartar una vez se crea una `SessionFactory`.

## 3.2. Obtención de una SessionFactory

Cuando la `org.hibernate.cfg.Configuration` ha analizado sintácticamente todos los mapeos, la aplicación tiene que obtener una fábrica para las instancias `org.hibernate.Session`. Esta fábrica está concebida para que todos los hilos de la aplicación la compartan:

    SessionFactory sessions = cfg.buildSessionFactory();

Hibernate permite que su aplicación instancie más de una `org.hibernate.SessionFactory`. Esto es útil si está utilizando más de una base de datos.

## 3.3. Conexiones JDBC

Se aconseja que la `org.hibernate.SessionFactory` cree y almacene en pool conexiones JDBC por usted Si adopta este enfoque, el abrir una `org.hibernate.Session` es tan simple como:

    Session session = sessions.openSession(); // open a new Session

En el momento en que inicie una tarea que requiera acceso a la base de datos, se obtendrá una conexión JDBC del pool.

Para que esto funcione, primero necesita pasar algunas las propiedades de conexión JDBC a Hibernate. Todos los nombres de las propiedades de Hibernate y su semántica están definidas en la clase `org.hibernate.cfg.Environment`. Ahora describiremos las configuraciones más importantes para la conexión JDBC.

Hibernate obtendrá y tendrá en pool las conexiones utilizando `java.sql.DriverManager` si configura las siguientes propiedades:

Tabla 3.1. Propiedades JDBC de Hibernate

Nombre de la propiedad | Propósito
--- | ---
hibernate.connection.driver_class | JDBC driver class
hibernate.connection.url | JDBC URL
hibernate.connection.username | database user
hibernate.connection.password | database user password
hibernate.connection.pool_size | maximum number of pooled connections

Sin embargo, el algoritmo de pooling de la conexión propia de Hibernate es algo rudimentario. Está concebido para ayudarle a comenzar y no para utilizarse en un sistema de producción ni siquiera para pruebas de rendimiento. Para alcanzar un mejor rendimiento y estabilidad debe utilizar un pool de terceros. Sólo remplace la propiedad hibernate.connection.pool_size con configuraciones específicas del pool de conexiones. Esto desactivará el pool interno de Hibernate. Por ejemplo, es posible utilizar C3P0.

C3P0 es un pool de conexiones JDBC de código abierto distribuido junto con Hibernate en el directorio `lib`. Hibernate utilizará su `org.hibernate.connection.C3P0ConnectionProvider` para pooling de conexiones si establece propiedades `hibernate.c3p0.*`. Si quiere utilizar Proxool refiérase a `hibernate.properties` incluído en el paquete y al sitio web de Hibernate para obtener más información.

Aquí hay un archivo `hibernate.properties` de ejemplo para c3p0:

    hibernate.connection.driver_class = org.postgresql.Driver
    hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
    hibernate.connection.username = myuser
    hibernate.connection.password = secret
    hibernate.c3p0.min_size=5
    hibernate.c3p0.max_size=20
    hibernate.c3p0.timeout=1800
    hibernate.c3p0.max_statements=50
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

Para su utilización dentro de un servidor de aplicaciones, casi siempre usted debe configurar Hibernate para obtener conexiones de un `javax.sql.Datasource` del servidor de aplicaciones registrado en JNDI. Necesitará establecer al menos una de las siguientes propiedades:

Tabla 3.2. Propiedades de la Fuente de Datos de Hibernate

Nombre de la propiedad | Propósito
--- | ---
hibernate.connection.datasource | datasource JNDI name
hibernate.jndi.url | URL del proveedor JNDI (opcional)
hibernate.jndi.class | clase del JNDI `InitialContextFactory` (opcional)
hibernate.connection.username | usuario de la base de datos (opcional)
hibernate.connection.password | contraseña del usuario de la base de datos (opcional)

He aquí un archivo `hibernate.properties` de ejemplo para una fuente de datos JNDI provisto por un servidor de aplicaciones:

    hibernate.connection.datasource = java:/comp/env/jdbc/test
    hibernate.transaction.factory_class = \
        org.hibernate.transaction.JTATransactionFactory
    hibernate.transaction.manager_lookup_class = \
        org.hibernate.transaction.JBossTransactionManagerLookup
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

Las conexiones JDBC obtenidas de una fuente de datos JNDI participarán automáticamente en las transacciones del servidor de aplicaciones administradas por el contenedor.

Pueden darse propiedades de conexión arbitrarias anteponiendo "`hibernate.connnection`" al nombre de propiedad de la conexión. Por ejemplo, puede especificar una propiedad de conexión `charSet` usando hibernate.connection.charSet.

Puede definir su propia estrategia plugin para obtener conexiones JDBC implementando la interfaz `org.hibernate.connection.ConnectionProvider` y especificando su propia implementación personalizada por medio de la propiedad hibernate.connection.provider_class.

## 3.4. Parámetros de configuración opcionales

Hay otras propiedades que controlan el comportamiento de Hibernate en tiempo de ejecución. Todas son opcionales y tienen valores razonables por defecto.

## Aviso

Algunas de estas propiedades se encuentran a "nivel del sistema sólamente". Las propiedades a nivel del sistema sólamente se pueden establecer por medio de `java -Dproperty=value` o `hibernate.properties`. No se pueden establecer por medio de las técnicas descritas anteriormente.

Tabla 3.3. Propiedades de Configuración de Hibernate

Nombre de la propiedad | Propósito
--- | ---

hibernate.dialect

El nombre de clase de un `org.hibernate.dialect.Dialect` de Hibernate, el cual le permite que genere un SQL optimizado para una base de datos relacional en particular.

e.g. `full.classname.of.Dialect`

En la mayoría de los casos Hibernate podrá de hecho seleccionar la implementación `org.hibernate.dialect.Dialect` correcta con base en los `JDBC metadata` que el controlador JDBC retorna.

hibernate.show_sql | Escribe todas las declaraciones SQL a la consola. Esta es una alternativa para establecer la categoria de registro `org.hibernate.SQL` a `debug`. e.g. `true` | `false`
hibernate.format_sql | Imprime el SQL en el registro y la consola. e.g. `true` | `false`
hibernate.default_schema | Califica los nombres de tabla sin calificar con el esquema/espacio de tabla dado en el SQL generado. e.g. `SCHEMA_NAME`
hibernate.default_catalog | Califica los nombres de tabla sin calificar con el catálogo dado en el SQL generado. e.g. `CATALOG_NAME`
hibernate.session_factory_name | Automáticamente se vinculará el `org.hibernate.SessionFactory` a este nombre en JNDI después de que se ha creado. e.g. `jndi/composite/name`
hibernate.max_fetch_depth | Establece una "profundidad" máxima del árbol de recuperación por unión externa (outer join) para asociaciones de un sólo extremo (uno-a-uno, muchos-a-uno). Un `0` deshabilita la recuperación por unión externa predeterminada. ej. los 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 predeterminado de representación de entidades para todas las sesiones abiertas desde esta `SessionFactory` `dynamic-map`, `dom4j`, `pojo`
hibernate.order_updates | Obliga a Hibernate a ordenar las actualizaciones SQL por el valor de la clave principal de los items a actualizar. Esto resultará en menos bloqueos de transacción en sistemas altamente concurrentes. e.g. `true` | `false`
hibernate.generate_statistics | De habilitarse, Hibernate colectará estadísticas útiles para la afinación de rendimiento. e.g. `true` | `false`
hibernate.use_identifier_rollback | De habilitarse, cuando se borren los objetos las propiedades identificadoras generadas se resetearán a losvalores establecidos por defecto. e.g. `true` | `false`
hibernate.use_sql_comments | De activarse, Hibernate generará comentarios dentro del SQL, para una depuración más fácil, por defecto es `false`. e.g. `true` | `false`
hibernate.id.new_generator_mappings | Setting is relevant when using `@GeneratedValue`. It indicates whether or not the new `IdentifierGenerator` implementations are used for `javax.persistence.GenerationType.AUTO`, `javax.persistence.GenerationType.TABLE` and `javax.persistence.GenerationType.SEQUENCE`. Default to `false` to keep backward compatibility. e.g. `true` | `false`

## Nota

We recommend all new projects which make use of to use `@GeneratedValue` to also set `hibernate.id.new_generator_mappings=true` as the new generators are more efficient and closer to the JPA 2 specification semantic. However they are not backward compatible with existing databases (if a sequence or a table is used for id generation).

Tabla 3.4. Propiedades de JDBC y Conexiones de Hibernate

Nombre de la propiedad | Propó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 que Hibernate utilice las actualizaciones en lote de JDBC2. ej. valores recomendados entre `5` y `30`
hibernate.jdbc.batch_versioned_data | Set this property to `true` if your JDBC driver returns correct row counts from `executeBatch()`. It is usually safe to turn this option on. Hibernate will then use batched DML for automatically versioned data. Defaults to `false`. e.g. `true` | `false`
hibernate.jdbc.factory_class | Selecciona un `org.hibernate.jdbc.Batcher` personalizado. La mayoría de las aplicaciones no necesitarán esta propiedad de configuración. eg. `classname.of.BatcherFactory`
hibernate.jdbc.use_scrollable_resultset | Habilita a Hibernate para utilizar los grupos de resultados deslizables de JDBC2. Esta propiedad sólamente es necesaria cuando se utilizan conexiones JDBC provistas por el usuario. En el caso contrario Hibernate utiliza los metadatos de conexión. e.g. `true` | `false`
hibernate.jdbc.use_streams_for_binary | Utiliza flujos (streams) al escribir/leer tipos `binary` o `serializable` a/desde JDBC. Propiedad a nivel de sistema e.g. `true` | `false`

hibernate.jdbc.use_get_generated_keys

Habilita el uso de `PreparedStatement.getGeneratedKeys()` de JDBC3 para recuperar claves generadas nativamente después de insertar. Requiere un controlador JDBC3+ y un JRE1.4+. Establézcalo como falso si su controlador tiene problemas con los generadores del identificador de Hibernate. Por defecto, se intenta determinar las capacidades del controlador utilizando los metadatos de conexión.

e.g. `true|false`

hibernate.connection.provider_class | EL nombre de clase de un `org.hibernate.connection.ConnectionProvider` personalizado que proporcione conexiones JDBC a Hibernate. e.g. `classname.of.ConnectionProvider`
hibernate.connection.isolation | Establece el nivel de aislamiento de la transacción JDBC. Comprueba `java.sql.Connection` para valores significativos pero observe que la mayoría de las bases de datos no soportan todos los niveles de aislamiento y algunos definen nivekes de aislamiento adicionales y no estándares. e.g. `1, 2, 4, 8`
hibernate.connection.autocommit | Habilita un guardado automático (autocommit) para las conexiones JDBC en pool (no se recomienda). e.g. `true` | `false`

hibernate.connection.release_mode

Especifica el momento en que Hibernate debe liberar las conexiones JDBC. Por defecto, una conexión JDBC es retenida hasta que la sesión se cierra o se desconecta explícitamente. Para una fuente de datos JTA del servidor de aplicaciones, debe utilizar `after_statement` para liberar agresivamente las conexiones después de cada llamada JDBC. Para una conexión no JTA, frecuentemente tiene sentido el liberar la conexión al final de cada transacción, el utilizar`after_transaction`. `auto` escogerá `after_statement` para las estrategias de transacción JTA y CMT y `after_transaction` para la estrategia JDBC de transacción.

e.g. `auto` (default) | `on_close` | `after_transaction` | `after_statement`

This setting only affects `Session`s returned from `SessionFactory.openSession`. For `Session`s obtained through `SessionFactory.getCurrentSession`, the `CurrentSessionContext` implementation configured for use controls the connection release mode for those `Session`s. See Sección 2.3, “Sesiones contextuales”

hibernate.connection.<propertyName> | Pasar la propiedad JDBC <propertyName> a `DriverManager.getConnection()`.
hibernate.jndi.<propertyName> | Pasar la propiedad <propertyName> al `InitialContextFactory` JNDI.

Tabla 3.5. Propiedades de Caché de Hibernate

Nombre de la propiedad | Propósito
--- | ---
`hibernate.cache.provider_class` | El nombre de clase de un `CacheProvider` personalizado. e.g. `classname.of.CacheProvider`
`hibernate.cache.use_minimal_puts` | Optimiza la operación del caché de segundo nivel para minimizar escrituras, con el costo de lecturas más frecuentes. Esta configuración es más útil para cachés en clúster y en Hibernate3, está habilitado por defecto para implementaciones de caché en clúster. e.g. `true|false`
`hibernate.cache.use_query_cache` | Habilita el caché de consultas. Las consultas individuales todavía tienen que establecerse con cachés. e.g. `true|false`
`hibernate.cache.use_second_level_cache` | Se puede utilizar para deshabilitar por completo el caché de segundo nivel, que está habilitado por defecto para clases que especifican un mapeo `<cache>`. e.g. `true|false`
`hibernate.cache.query_cache_factory` | El nombre de clase de una interfaz `QueryCache` personalizada, por defecto al `StandardQueryCache` incorporado. e.g. `classname.of.QueryCache`
`hibernate.cache.region_prefix` | Un prefijo que se debe utilizar para los nombres de región del caché de segundo nivel. e.g. `prefix`
`hibernate.cache.use_structured_entries` | Obliga a Hibernate a almacenar los datos en el caché de segundo nivel en un formato más amigable para personas. e.g. `true|false`
`hibernate.cache.default_cache_concurrency_strategy` | Setting used to give the name of the default `org.hibernate.annotations.CacheConcurrencyStrategy` to use when either `@Cacheable` or `@Cache` is used. `@Cache(strategy="..")` is used to override this default.

Tabla 3.6. Propiedades de Transacción de Hibernate

Nombre de la propiedad | Propósito
--- | ---
`hibernate.transaction.factory_class` | El nombre de clase de un `TransactionFactory` a utilizar con la API de `Transaction` de Hibernate (por defecto es `JDBCTransactionFactory`). e.g. `classname.of.TransactionFactory`
`jta.UserTransaction` | Un nombre JNDI utilizado por `JTATransactionFactory` para obtener la `UserTransaction` de JTA del servidor de aplicaciones. e.g. `jndi/composite/name`
`hibernate.transaction.manager_lookup_class` | El nombre de clase de un `TransactionManagerLookup`. Se requiere cuando el chaché a nivel de MVJ está habilitado o cuando se utiliza un generador alto/bajo en un entorno JTA. e.g. `classname.of.TransactionManagerLookup`
`hibernate.transaction.flush_before_completion` | If enabled, the session will be automatically flushed during the before completion phase of the transaction. Built-in and automatic session context management is preferred, see Sección 2.3, “Sesiones contextuales”. e.g. `true` | `false`
`hibernate.transaction.auto_close_session` | If enabled, the session will be automatically closed during the after completion phase of the transaction. Built-in and automatic session context management is preferred, see Sección 2.3, “Sesiones contextuales”. e.g. `true` | `false`

Tabla 3.7. Propiedades Misceláneas

Nombre de la propiedad | Propósito
--- | ---
`hibernate.current_session_context_class` | Supply a custom strategy for the scoping of the "current" `Session`. See Sección 2.3, “Sesiones contextuales” for more information about the built-in strategies. e.g. `jta` | `thread` | `managed` | `custom.Class`
`hibernate.query.factory_class` | Elige la implementación de análisis sintáctico HQL. ej. `org.hibernate.hql.ast.ASTQueryTranslatorFactory` o `org.hibernate.hql.classic.ClassicQueryTranslatorFactory`
`hibernate.query.substitutions` | Se utiliza para mapear desde tokens en consultas Hibernate a tokens SQL. (por ejemplo, los tokens pueden ser nombres de función o literales). e.g. `hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC`
`hibernate.hbm2ddl.auto` | Exporta o valida automáticamente DDL de esquema a la base de datos cuando se crea la `SessionFactory`. Con `create-drop` se desechará el esquema de la base de datos cuando la `SessionFactory` se cierre explícitamente. e.g. `validate` | `update` | `create` | `create-drop`

`hibernate.hbm2ddl.import_files`

Comma-separated names of the optional files containing SQL DML statements executed during the `SessionFactory` creation. This is useful for testing or demoing: by adding INSERT statements for example you can populate your database with a minimal set of data when it is deployed.

File order matters, the statements of a give file are executed before the statements of the following files. These statements are only executed if the schema is created ie if `hibernate.hbm2ddl.auto` is set to `create` or `create-drop`.

e.g. `/humans.sql,/dogs.sql`

`hibernate.bytecode.use_reflection_optimizer` | Enables the use of bytecode manipulation instead of runtime reflection. This is a System-level property and cannot be set in `hibernate.cfg.xml`. Reflection can sometimes be useful when troubleshooting. Hibernate always requires either CGLIB or javassist even if you turn off the optimizer. e.g. `true` | `false`
`hibernate.bytecode.provider` | Both javassist or cglib can be used as byte manipulation engines; the default is `javassist`. e.g. `javassist` | `cglib`

### 3.4.1. Dialectos de SQL

Siempre configure la propiedad `hibernate.dialect` a la subclase correcta `org.hibernate.dialect.Dialect` para su base de datos. Si especifica un dialecto, Hibernate utilizará valores predeterminados de manera sensible para algunas de las otras propiedades enumeradas anteriormente, ahorrándole el esfuerzo de especificarlas manualmente.

Tabla 3.8. Dialectos SQL de Hibernate(`hibernate.dialect`)

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`
MySQL5 | `org.hibernate.dialect.MySQL5Dialect`
MySQL5 with InnoDB | `org.hibernate.dialect.MySQL5InnoDBDialect`
MySQL con MyISAM | `org.hibernate.dialect.MySQLMyISAMDialect`
Oracle (cualquier versión) | `org.hibernate.dialect.OracleDialect`
Oracle 9i | `org.hibernate.dialect.Oracle9iDialect`
Oracle 10g | `org.hibernate.dialect.Oracle10gDialect`
Oracle 11g | `org.hibernate.dialect.Oracle10gDialect`
Sybase | `org.hibernate.dialect.SybaseASE15Dialect`
Sybase Anywhere | `org.hibernate.dialect.SybaseAnywhereDialect`
Microsoft SQL Server 2000 | `org.hibernate.dialect.SQLServerDialect`
Microsoft SQL Server 2005 | `org.hibernate.dialect.SQLServer2005Dialect`
Microsoft SQL Server 2008 | `org.hibernate.dialect.SQLServer2008Dialect`
SAP DB | `org.hibernate.dialect.SAPDBDialect`
Informix | `org.hibernate.dialect.InformixDialect`
HypersonicSQL | `org.hibernate.dialect.HSQLDialect`
H2 Database | `org.hibernate.dialect.H2Dialect`
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`

### 3.4.2. Recuperación por Unión Externa - Outer Join Fetching

Si su base de datos soporta uniones externas del estilo ANSI, Oracle o Sybase, frecuentemente la recuperación por unión externa aumentará el rendimiento limitando el número de llamadas a la base de datos. La recuperación por unión externa permite que un gráfico completo de objetos conectados por asociaciones muchos-a-uno, uno-a-muchos, muchos-a-muchos y uno-a-uno sea recuperado en un sólo `SELECT` SQL.

La recuperación por unión externa puede ser deshabilitada globalmente estableciendo la propiedad `hibernate.max_fetch_depth` como `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"`.

See Sección 21.1, “Estrategias de recuperación” for more information.

### 3.4.3. Flujos Binarios

Oracle limita el tamaño de arrays de `byte` que se puedan pasar a/desde su controlador JDBC. Si desea utilizar instancias grandes de tipo `binary` o `serializable`, usted debe habilitar `hibernate.jdbc.use_streams_for_binary`. Esta es una configuración a nivel de sistema sólamente.

### 3.4.4. Caché de segundo nivel y de lectura

The properties prefixed by `hibernate.cache` allow you to use a process or cluster scoped second-level cache system with Hibernate. See the Sección 21.2, “El Caché de Segundo Nivel” for more information.

### 3.4.5. Sustitución de Lenguaje de Consulta

Puede definir nuevos tokens de consulta de Hibernate utilizando `hibernate.query.substitutions`. Por ejemplo:

    hibernate.query.substitutions true=1, false=0

Esto causaría que los tokens `true` y `false` sean traducidos a literales enteros en el SQL generado.

    hibernate.query.substitutions toLowercase=LOWER

Esto le permitiría renombrar la función `LOWER` de SQL.

### 3.4.6. Estadísticas de Hibernate

Si habilita `hibernate.generate_statistics`, Hibernate expondrá un número de métricas que son útiles al afinar un sistema en ejecución por medio de `SessionFactory.getStatistics()`. Incluso se puede configurar Hibernate para exponer estas estadísticas por medio de JMX. Lea el Javadoc de las interfaces en `org.hibernate.stats` para obtener más información.

## 3.5. Registros de mensajes (Logging)

Hibernate utiliza Simple Logging Facade for Java (SLF4J) con el fin de registrar varios eventos del sistema. SLF4J puede direccionar su salida de registro a varios marcos de trabajo de registro (NOP, Simple, log4j versión 1.2, JDK 1.4 logging, JCL o logback) dependiendo de su enlace escogido. Con el fin de configurar el registro necesitará `slf4j-api.jar` en su ruta de clase junto con el archivo jar para su enlace preferido - `slf4j-log4j12.jar` en el caso de Log4J. Consulte la documentación SLF4J para obtener mayores detalles. Para usar Log4j también necesitará poner un archivo `log4j.properties` en su ruta de clase. Un archivo de propiedades de ejemplo se distribuye junto con Hibernate en el directorio `src/`.

Le recomendamos bastante que se familiarice con los mensajes de registro de Hibernate. Se ha trabajado bastante para hacer que los registros de Hibernate sean tan detallados como sea posible, sin hacerlos ilegibles. Es un dispositivo esencial en la resolución de problemas. Las categorías de registro más interesantes son las siguientes:

Tabla 3.9. Categorías de Registro de Hibernate

Categoría | Función
--- | ---
`org.hibernate.SQL` | Registra todas las declaraciones DML de SQL a medida que se ejecutan
`org.hibernate.type` | Registra todos los parámetros JDBC
`org.hibernate.tool.hbm2ddl` | Registra todas las declaraciones DDL de SQL a medida que se ejecutan
`org.hibernate.pretty` | Registra el estado de todas las entidades (máximo 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.AST` | Regista los ASTs de HQL y SQL, durante análisis de consultas.
`org.hibernate.secure` | Registra todas las peticiones de autorización JAAS
`org.hibernate` | Registra todo. Hay mucha información, pero es útil para la resolución de problemas

Al desarrollar aplicaciones con Hibernate, casi siempre debe trabajar con `debug` habilitado para la categoría `org.hibernate.SQL` o, alternativamente, la propiedad `hibernate.show_sql` habilitada.

## 3.6. Implementación de una `NamingStrategy`

La interfaz `org.hibernate.cfg.NamingStrategy` le permite especificar un "estándar de nombrado" para objetos de la base de datos y los elementos del esquema.

Puede proveer reglas para generar automáticamente identificadores de la base de datos a partir de identificadores JDBC o para procesar nombres "lógicos" de columnas y tablas dadas en el archivo de mapeo en nombres "físicos" de columnas y tablas. Esta funcionalidad ayuda a reducir la verborragia del documento de mapeo, eliminando ruidos repetitivos (por ejemplo, prefijos `TBL_`). Hibernate utiliza una estrategia por defecto bastante mínima.

Puede especificar una estrategia diferente llamando a `Configuration.setNamingStrategy()` antes de agregar los mapeos:

    SessionFactory sf = new Configuration()

        .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)

        .addFile("Item.hbm.xml")

        .addFile("Bid.hbm.xml")

        .buildSessionFactory();

`org.hibernate.cfg.ImprovedNamingStrategy` es una estrategia incorporada que puede ser un punto de partida útil para algunas aplicaciones.

## 3.7. Implementing a PersisterClassProvider

You can configure the persister implementation used to persist your entities and collections:

- by default, Hibernate uses persisters that make sense in a relational model and follow Java Persistence's specification

- you can define a `PersisterClassProvider` implementation that provides the persister class used of a given entity or collection

- finally, you can override them on a per entity and collection basis in the mapping using `@Persister` or its XML equivalent

The latter in the list the higher in priority.

You can pass the `PersisterClassProvider` instance to the `Configuration` object.

    SessionFactory sf = new Configuration()

        .setPersisterClassProvider(customPersisterClassProvider)

        .addAnnotatedClass(Order.class)

        .buildSessionFactory();

The persister class provider methods, when returning a non null persister class, override the default Hibernate persisters. The entity name or the collection role are passed to the methods. It is a nice way to centralize the overriding logic of the persisters instead of spreading them on each entity or collection mapping.

## 3.8. Archivo de configuración XML

Un enfoque alternativo de configuración es especificar una configuración completa en un archivo llamado `hibernate.cfg.xml`. Este archivo se puede utilizar como un remplazo del archivo `hibernate.properties` o en el caso de que ambos se encuentren presentes, para sobrescribir propiedades.

El archivo de configuración XML por defecto se espera en la raíz de su `CLASSPATH`. Este es un ejemplo:

    <?xml version='1.0' encoding='utf-8'?>

    <!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD//EN"

        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <!-- a SessionFactory instance listed as /jndi/name -->

        <session-factory

            name="java:hibernate/SessionFactory">

            <!-- properties -->

            <property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>

            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

            <property name="show_sql">false</property>

            <property name="transaction.factory_class">

                org.hibernate.transaction.JTATransactionFactory

            </property>

            <property name="jta.UserTransaction">java:comp/UserTransaction</property>

            <!-- mapping files -->

            <mapping resource="org/hibernate/auction/Item.hbm.xml"/>

            <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>

            <!-- cache settings -->

            <class-cache class="org.hibernate.auction.Item" usage="read-write"/>

            <class-cache class="org.hibernate.auction.Bid" usage="read-only"/>

            <collection-cache collection="org.hibernate.auction.Item.bids" usage="read-write"/>

        </session-factory>

    </hibernate-configuration>

La ventaja de este enfoque es la externalización de los nombres de los archivos de mapeo a la configuración. El `hibernate.cfg.xml` también es más práctico una vez que haya afinado el caché de Hibernate. Puede escoger ya sea `hibernate.properties` o `hibernate.cfg.xml`. Ambos son equivalentes, excepto por los beneficios de utilizar la sintaxis XML que mencionados anteriormente.

Con la configuración XML, iniciar Hibernate es tan simple como:

    SessionFactory sf = new Configuration().configure().buildSessionFactory();

Puede seleccionar un fichero de configuración XML diferente utilizando:

    SessionFactory sf = new Configuration()

        .configure("catdb.cfg.xml")

        .buildSessionFactory();

## 3.9. Java EE Application Server integration

Hibernate tiene los siguientes puntos de integración con la infraestructura J2EE:

- Fuentes de datos administrados por el contenedor: Hibernate puede utilizar conexiones JDBC administradas por el contenedor y provistas a través de JNDI. Usualmente, un `TransactionManager` compatible con JTA y un `ResourceManager` se ocupan de la administración de transacciones (CMT), especialmente del manejo de transacciones distribuídas a través de varias fuentes de datos. También puede demarcar los límites de las transacciones programáticamente (BMT) o puede que quiera utilizar para esto la API opcional de `Transaction` de Hibernate para mantener portátil su código.

- Vinculación Automática JNDI: Hibernate puede vincular sus `SessionFactory` a JNDI después del inicio.

- Vinculación de Sesión JTA: La `Session` de Hibernate se puede vincular automáticamente al ámbito de transacciones JTA. Simplemente busque la `SessionFactory` de JNDI y obténga la `Session` actual. Deje que Hibernate se ocupe de vaciar y cerrar la `Session` cuando se complete su transacción JTA. La demarcación de transacción puede ser declarativa (CMT) o programática (BMT/UserTransaction).

- Despliegue JMX: Si tiene un servidor de aplicaciones con capacidad para JMX (por ejemplo, JBoss AS), puede escoger el desplegar Hibernate como un MBean administrado. Esto le ahorra el código de una línea de inicio para construir su `SessionFactory` desde una `Configuration`. El contenedor iniciará su `HibernateService`, e idealmente también cuidará de las dependencias entre servicios (la fuente de datos debe estar disponible antes de que Hibernate inicie, etc).

Dependiendo de su entorno, podría tener que establecer la opción de configuración `hibernate.connection.aggressive_release` como true si su servidor de aplicaciones muestra excepciones "contención de conexión".

### 3.9.1. Configuración de la estrategia de transacción

La API de `Session` de Hibernate es independiente de cualquier demarcación de transacción en su arquitectura. Si deja que Hibernate utilice JDBC directamente, a través de un pool de conexiones, puede comenzar y acabar sus transacciones llamando la API de JDBC. Si ejecuta en un servidor de aplicaciones J2EE, puede que quiera utilizar transacciones administradas por bean y llamar la API de JTA y `UserTransaction` cuando sea necesario.

Para mantener su código portable entre estos dos (y otros) entornos le recomendamos la API de `Transaction` de Hibernate, que envuelve y oculta el sistema subyacente. Tiene que especificar una clase fábrica para las instancias de `Transaction` estableciendo la propiedad de configuración `hibernate.transaction.factory_class` de Hibernate.

Existen tres opciones estándares o incorporadas:

`org.hibernate.transaction.JDBCTransactionFactory`

  delega a transacciones de bases de datos (JDBC) (por defecto)

`org.hibernate.transaction.JTATransactionFactory`

  delega a transacciones administradas por el contenedor si una transacción existente se encuentra en proceso en este contexto (por ejemplo, un método de bean de sesión EJB). De otra manera, se inicia una nueva transacción y se utilizan las transacciones administradas por bean.

`org.hibernate.transaction.CMTTransactionFactory`

  delega a transacciones JTA administradas por el contenedor

También puede definir sus propias estrategias de transacción (por ejemplo, para un servicio de transacción CORBA).

Algunas funcionalidades en Hibernate (por ejemplo, el caché de segundo nivel, las sesiones contextuales, etc.) requieren acceso al `TransactionManager` de JTA en un entorno administrado. En un servidor de aplicaciones tiene que especificar cómo Hibernate debe obtener una referencia al `TransactionManager`, ya que J2EE no estandariza un sólo mecanismo:

Tabla 3.10. TransactionManagers de JTA

Transaction Factory | Servidor de Aplicaciones
--- | ---
`org.hibernate.transaction.JBossTransactionManagerLookup` | JBoss AS
`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
`org.hibernate.transaction.JBossTSStandaloneTransactionManagerLookup` | JBoss TS used standalone (ie. outside JBoss AS and a JNDI environment generally). Known to work for `org.jboss.jbossts:jbossjta:4.11.0.Final`

### 3.9.2. `SessionFactory` enlazado a JNDI

Una `SessionFactory` de Hibernate vinculada a JNDI puede simplificar la búsqueda de la fábrica y la creación de nuevas `Session`es. Sin embargo, esto no se relaciona con un `Datasource` vinculado a JNDI; simplemente que ambos utilizan el mismo registro.

Si desea tener la `SessionFactory` vinculada a un espacio de nombres de JNDI, especifique un nombre (por ejemplo, `java:hibernate/SessionFactory`) utilizando la propiedad `hibernate.session_factory_name`. Si se omite esta propiedad, la `SessionFactory` no será vinculada a JNDI. Esto es particularmente útil en entornos con una implementación JNDI de sólo lectura por defecto (por ejemplo, en Tomcat).

Al vincular la `SessionFactory` a JNDI, Hibernate utilizará los valores de `hibernate.jndi.url`, `hibernate.jndi.class` para instanciar un contexto inicial. Si éstos no se especifican, se utilizará el `InitialContext` por defecto.

Hibernate colocará automáticamente la `SessionFactory` en JNDI después de que llame a `cfg.buildSessionFactory()`. Esto significa que tendrá al menos esta llamada en algún código de inicio o clase de utilidad en su aplicación, a menos de que utilice el despliegue JMX con el `HibernateService` (esto se discute más adelante en mayor detalle).

Si utiliza una `SessionFactory` JNDI, un EJB or cualquier otra clase puede llegar a obtener el `SessionFactory` utilizando una búsqueda JNDI.

It is recommended that you bind the `SessionFactory` to JNDI in a managed environment and use a `static` singleton otherwise. To shield your application code from these details, we also recommend to hide the actual lookup code for a `SessionFactory` in a helper class, such as `HibernateUtil.getSessionFactory()`. Note that such a class is also a convenient way to startup Hibernate—see chapter 1.

### 3.9.3. Administración de contexto de Sesión Actual con JTA

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

### 3.9.4. Despliegue JMX

La línea `cfg.buildSessionFactory()` todavía se tiene que ejecutar en algún sitio para obtener una `SessionFactory` en JNDI. Puede hacer esto ya sea en un bloque inicializador `static` (como aquel en `HibernateUtil`) o bien puede desplegar Hibernate como un servicio administrado.

Hibernate se distribuye con `org.hibernate.jmx.HibernateService` para desplegar en un servidor de aplicaciones con capacidades JMX, como JBoss AS. El despliegue y la configuracón reales son específicos del vendedor. He aquí un ejemplo de `jboss-service.xml` para JBoss 4.0.x:

    <?xml version="1.0"?>

    <server>

    <mbean code="org.hibernate.jmx.HibernateService"

        name="jboss.jca:service=HibernateFactory,name=HibernateFactory">

        <!-- Required services -->

        <depends>jboss.jca:service=RARDeployer</depends>

        <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>

        <!-- Bind the Hibernate service to JNDI -->

        <attribute name="JndiName">java:/hibernate/SessionFactory</attribute>

        <!-- Datasource settings -->

        <attribute name="Datasource">java:HsqlDS</attribute>

        <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>

        <!-- Transaction integration -->

        <attribute name="TransactionStrategy">

            org.hibernate.transaction.JTATransactionFactory</attribute>

        <attribute name="TransactionManagerLookupStrategy">

            org.hibernate.transaction.JBossTransactionManagerLookup</attribute>

        <attribute name="FlushBeforeCompletionEnabled">true</attribute>

        <attribute name="AutoCloseSessionEnabled">true</attribute>

        <!-- Fetching options -->

        <attribute name="MaximumFetchDepth">5</attribute>

        <!-- Second-level caching -->

        <attribute name="SecondLevelCacheEnabled">true</attribute>

        <attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>

        <attribute name="QueryCacheEnabled">true</attribute>

        <!-- Logging -->

        <attribute name="ShowSqlEnabled">true</attribute>

        <!-- Mapping files -->

        <attribute name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>

    </mbean>

    </server>

Este archivo se implementa en un directorio llamado `META-INF` y se encuentra empacado en un archivo JAR con la extensión `.sar` (archivo de servicio). También necesita empacar Hibernate, sus bibliotecas de terceros requeridas, sus clases persistentes compiladas, así como sus archivos de mapeo en el mismo archivo. Sus beans empresariales (usualmente beans de sesión) se pueden dejar en su propio archivo JAR, pero puede incluir este archivo EJB JAR en el archivo de servicio principal para obtener una unidad desplegable en vivo (sin apagarlo). Consulte la documentación de JBoss AS para obtener más información sobre el servicio JMX y la implementación de EJB.

Copyright © 2004 Red Hat, Inc.

- AnteriorCapítulo 2. Arquitectura
- Subir
- Inicio
- SiguienteCapítulo 4. Clases persistentes