Hibernate.org Community Documentation

- Précédent
- Suivant

## Chapitre 3. Configuration

Hibernate est conçu pour fonctionner dans de nombreux environnements , c'est pourquoi il existe beaucoup de paramètres de configuration. Heureusement, la plupart ont des valeurs par défaut appropriées et la Hibernate inclut un fichier d'exemples `hibernate.properties` dans le répertoire `etc/` qui fournit les différentes options. Vous n'avez qu'à placer ce fichier dans votre classpath et à l'adapter à vos besoins.

## 3.1. Configuration par programmation

Une instance de `org.hibernate.cfg.Configuration` représente un ensemble de mappages des classes Java d'une application vers la base de données SQL. La `Configuration` est utilisée pour construire un objet (immuable) `SessionFactory`. Les mappages sont constitués d'un ensemble de fichiers de mappage XML.

Vous pouvez obtenir une instance de `Configuration` en l'instanciant directement et en spécifiant la liste des documents XML de mappage. Si les fichiers de mappage sont dans le classpath, vous pouvez utiliser la méthode `addResource()` :

    Configuration cfg = new Configuration()

        .addResource("Item.hbm.xml")

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

Une solution alternative consiste à spécifier la classe mappée et à donner à Hibernate la possibilité de trouver les documents de mappage pour vous :

    Configuration cfg = new Configuration()

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

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

Hibernate va rechercher les fichiers de mappages `/org/hibernate/auction/Item.hbm.xml` et `/org/hibernate/auction/Bid.hbm.xml` dans le classpath. Cette approche élimine les noms de fichiers en dur.

Une `Configuration` vous permet également de préciser des propriétés de configuration. Par exemple :

    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");

Ce n'est pas le seul moyen de passer des propriétés de configuration à Hibernate. Les différentes options sont :

1. Passer une instance de `java.util.Properties` à `Configuration.setProperties()`.

2. Placer `hibernate.properties` dans un répertoire racine du chemin de classe.

3. Positionner les propriétés `System` en utilisant `java -Dproperty=value`.

4. Inclure des éléments `<property>` dans le fichier `hibernate.cfg.xml` (voir plus loin).

Si vous souhaitez démarrer rapidement, `hibernate.properties` est l'approche la plus facile.

`org.hibernate.cfg.Configuration` est un objet de démarrage qui sera supprimé une fois qu'une `SessionFactory` aura été créée.

## 3.2. Obtenir une SessionFactory

When all mappings have been parsed by the `org.hibernate.cfg.Configuration`, the application must obtain a factory for `org.hibernate.Session` instances. This factory is intended to be shared by all application threads:

    SessionFactory sessions = cfg.buildSessionFactory();

Hibernate does allow your application to instantiate more than one `org.hibernate.SessionFactory`. This is useful if you are using more than one database.

## 3.3. Connexions JDBC

Il est conseillé que `org.hibernate.SessionFactory` crée les connexions JDBC et les mette dans un pool pour vous. Si vous suivez cette approche, ouvrir une `org.hibernate.Session` est aussi simple que :

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

Dès que vous initierez une action qui requiert un accès à la base de données, une connexion JDBC sera récupérée dans le pool.

À cet effet, il faut passer les propriétés de la connexion JDBC à Hibernate. Tous les noms des propriétés Hibernate et leur signification sont définies dans la classe `org.hibernate.cfg.Environment`. Nous allons maintenant décrire les paramètres de configuration des connexions JDBC les plus importants.

Hibernate obtiendra des connexions (et les mettra dans un pool) en utilisant `java.sql.DriverManager` si vous positionnez les paramètres de la manière suivante :

Tableau 3.1. Propriétés JDBC de Hibernate

Nom de la propriété | Fonction
--- | ---
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

L'algorithme natif de pool de connexions de Hibernate est plutôt rudimentaire. Il a été conçu dans le but de vous aider à démarrer et n'est pas prévu pour un système en production ou même pour un test de performance. Utilisez plutôt un pool tiers pour de meilleures performances et une meilleure stabilité : remplacez la propriété `hibernate.connection.pool_size` avec les propriétés spécifiques au pool de connexions que vous avez choisi. Cela désactivera le pool de connexions interne de Hibernate. Vous pouvez par exemple utiliser C3P0.

C3P0 est un pool de connexions JDBC open source distribué avec Hibernate dans le répertoire `lib`. Hibernate utilisera son provider `C3P0ConnectionProvider` pour le pool de connexions si vous configurez les propriétés `hibernate.c3p0.*`. Si vous voulez utiliser Proxool, référez vous au groupe de propriétés `hibernate.properties` correspondant et consultez le site web Hibernate pour plus d'informations.

Voici un exemple de fichier `hibernate.properties` pour 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

Pour l'utilisation de Hibernate au sein d'un serveur d'applications, il est recommandé de configurer Hibernate presque toujours de façon à ce qu'il obtienne ses connexions de la `DataSource` enregistrée du serveur d'applications dans le JNDI. À cet effet, vous devrez définir au moins une des propriétés suivantes :

Tableau 3.2. Propriétés d'une Datasource Hibernate

Nom de la propriété | Fonction
--- | ---
hibernate.connection.datasource | datasource JNDI name
hibernate.jndi.url | URL du fournisseur JNDI (optionnel)
hibernate.jndi.class | classe de JNDI `InitialContextFactory` (optionnel)
hibernate.connection.username | utilisateur de base de données (optionnel)
hibernate.connection.password | mot de passe de l'utilisateur de base de données (optionnel)

Voici un exemple de fichier `hibernate.properties` pour l'utilisation d'une datasource JNDI fournie par un serveur d'applications :

    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

Les connexions JDBC obtenues à partir d'une datasource JNDI participeront automatiquement aux transactions gérées par le conteneur du serveur d'applications.

Des propriétés arbitraires de connexion peuvent être passées en préfixant le nom de la propriété par "`hibernate.connnection`". Par exemple, vous pouvez spécifier un `charSet` en utilisant `hibernate.connection.charSet`.

Vous pouvez fournir votre propre stratégie d'obtention des connexions JDBC en implémentant l'interface `org.hibernate.connection.ConnectionProvider`. Vous pouvez sélectionner une implémentation spécifique par la propriété `hibernate.connection.provider_class`.

## 3.4. Propriétés de configuration optionnelles

Il y a un certain nombre d'autres propriétés qui contrôlent le fonctionnement d'Hibernate à l'exécution. Toutes sont optionnelles et ont comme valeurs par défaut des valeurs raisonnables.

## Avertissement

Some of these properties are "system-level" only. System-level properties can be set only via `java -Dproperty=value` or `hibernate.properties`. They cannot be set by the other techniques described above.

Tableau 3.3. Propriétés de configuration Hibernate

Nom de la propriété | Fonction
--- | ---
hibernate.dialect | Le nom de la classe d'un `org.hibernate.dialect.Dialect` Hibernate qui permet à Hibernate de générer du SQL optimisé pour une base de données relationnelle particulière. par ex.`full.classname.of.Dialect` Dans la plupart des cas, Hibernate sera en mesure de choisir l'implémentation `org.hibernate.dialect.Dialect` qui convient sur la base des `métadonnées JDBC` retournées par le driver JDBC.
hibernate.show_sql | Écrit toutes les requêtes SQL sur la console. Il s'agit d'une alternative au paramétrage de la catégorie de log `org.hibernate.SQL` à `debug`. par ex.`true` | `false`
hibernate.format_sql | Effectue un pretty print du SQL dans la console et dans le log. par ex.`true` | `false`
hibernate.default_schema | Qualifie des noms de table non qualifiés avec le schéma/tablespace dans le SQL généré. e.g. `SCHEMA_NAME`
hibernate.default_catalog | Qualifie les noms de tables non qualifiées avec ce catalogue dans le SQL généré. e.g. `CATALOG_NAME`
hibernate.session_factory_name | `org.hibernate.SessionFactory` sera automatiquement liée à ce nom dans JNDI après sa création. par ex.`jndi/composite/name`
hibernate.max_fetch_depth | Configure la profondeur maximale d'un arbre de chargement par jointures externes pour les associations à cardinalité unitaire (un-à-un, plusieurs-à-un). Un `0` désactive le chargement par défaut par jointure externe. par ex. valeurs recommandées entre `0` et `3`
hibernate.default_batch_fetch_size | Configure une taille par défaut pour le chargement par lot des associations Hibernate ex. valeurs recommandées : `4`, `8`, `16`
hibernate.default_entity_mode | Sets a default mode for entity representation for all sessions opened from this `SessionFactory` `dynamic-map`, `dom4j`, `pojo`
hibernate.order_updates | Force Hibernate à trier les mises à jour SQL par la valeur de la clé primaire des éléments mis à jour. Cela permet de limiter les deadlocks de transaction dans les systèmes hautement concurrents. par ex.`true` | `false`
hibernate.generate_statistics | Si activé, Hibernate va collecter des statistiques utiles pour le réglage des performances. par ex.`true` | `false`
hibernate.use_identifier_rollback | Si activé, les propriétés correspondant à l'identifiant des objets sont remises aux valeurs par défaut lorsque les objets sont supprimés. par ex.`true` | `false`
hibernate.use_sql_comments | Si activé, Hibernate génère des commentaires à l'intérieur des requêtes SQL pour faciliter le débogage, par défaut à `false`. par ex.`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. par ex.`true` | `false`

## Note

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

Tableau 3.4. Propriétés Hibernate liées à JDBC et aux connexions

Nom de la propriété | Fonction
--- | ---
hibernate.jdbc.fetch_size | Une valeur non nulle détermine la taille des chargements JDBC (appelle `Statement.setFetchSize()`).
hibernate.jdbc.batch_size | Une valeur non nulle active l'utilisation par Hibernate des mise à jour par lot de JDBC2. ex. les valeurs recommandées entre `5` et `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`. par ex.`true` | `false`
hibernate.jdbc.factory_class | Sélectionne un `org.hibernate.jdbc.Batcher` personnalisé. La plupart des applications n'auront pas besoin de cette propriété de configuration. par.ex. `classname.of.BatcherFactory`
hibernate.jdbc.use_scrollable_resultset | Active l'utilisation par Hibernate des ensembles de résultats déroulants de JDBC2. Cette propriété est seulement nécessaire lorsque l'on utilise des connexions JDBC fournies par l'utilisateur. Autrement, Hibernate utilise les métadonnées de la connexion. par ex.`true` | `false`
hibernate.jdbc.use_streams_for_binary | Utilise des flux lorsque l'on écrit/lit des types `binary` ou des types `serializable`vers/à partir de JDBC. *system-level property* par ex.`true` | `false`
hibernate.jdbc.use_get_generated_keys | Active l'utilisation de `PreparedStatement.getGeneratedKeys()` de JDBC3 pour récupérer nativement les clés générées après insertion. Nécessite un pilote JDBC3+ et JRE1.4+, configurés à false si votre pilote a des problèmes avec les générateurs d'identifiant Hibernate. Par défaut, essaie de déterminer les possibilités du pilote en utilisant les metadonnées de connexion. par ex. `true|false`
hibernate.connection.provider_class | Le nom de la classe d'un `org.hibernate.connection.ConnectionProvider` personnalisé qui fournit des connexions JDBC à Hibernate. par ex.`classname.of.ConnectionProvider`
hibernate.connection.isolation | Définit le niveau d'isolation des transactions JDBC. Regardez `java.sql.Connection` pour des valeurs significatives mais notez également que la plupart des bases de données ne supportent pas tous les niveaux d'isolation et que certaines définissent des isolations non standard supplémentaires. par ex.`1, 2, 4, 8`
hibernate.connection.autocommit | Active le mode de commit automatique (autocommit) pour les connexions JDBC du pool (non recommandé). par ex.`true` | `false`
hibernate.connection.release_mode | Spécifie à quel moment Hibernate doit relâcher les connexions JDBC. Par défaut, une connexion JDBC est conservée jusqu'à ce que la session soit explicitement fermée ou déconnectée. Pour une source de données JTA d'un serveur d'applications, vous devriez utiliser `after_statement` pour libérer les connexions de manière plus agressive après chaque appel JDBC. Pour une connexion non JTA, il est souvent préférable de libérer la connexion à la fin de chaque transaction en utilisant `after_transaction`. `auto` choisira `after_statement` pour les stratégies de transactions JTA et CMT et `after_transaction` pour des stratégies de transactions JDBC. 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 Section 2.3, « Sessions contextuelles »
hibernate.connection.<propertyName> | Passez une propriété JDBC `propertyName` à `DriverManager.getConnection()`.
hibernate.jndi.<propertyName> | Passez la propriété <propertyName> au JNDI `InitialContextFactory`.

Tableau 3.5. Propriétés du Cache Hibernate

Nom de la propriété | Fonction
--- | ---
`hibernate.cache.provider_class` | Le nom de classe d'un `CacheProvider` personnalisé. par ex.`classname.of.CacheProvider`
`hibernate.cache.use_minimal_puts` | Optimise le cache de second niveau en minimisant les écritures, au prix de plus de lectures. Ce paramètre est surtout utile pour les caches en cluster,et est activé par défaut dans hibernate3 pour les implémentations de cache en cluster. par ex. `true|false`
`hibernate.cache.use_query_cache` | Activer le cache de requête, les requêtes individuelles doivent tout de même être déclarées comme pouvant être mises en cache. par ex. `true|false`
`hibernate.cache.use_second_level_cache` | Peut être utilisé pour désactiver complètement le cache de second niveau qui est activé par défaut pour les classes qui spécifient un élément `<cache>` dans leur mappage. par ex. `true|false`
`hibernate.cache.query_cache_factory` | Le nom de classe d'une interface `QueryCache` personnalisée, par défaut prend la valeur du `StandardQueryCache` imbriqué. par ex.`classname.of.QueryCache`
`hibernate.cache.region_prefix` | Un préfixe à utiliser pour les noms de régions du cache de second niveau. par ex. `prefix`
`hibernate.cache.use_structured_entries` | Force Hibernate à stocker les données dans le cache de second niveau en un format plus adapté à la visualisation. par ex. `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.

Tableau 3.6. Propriétés des transactions Hibernate

Nom de la propriété | Fonction
--- | ---
`hibernate.transaction.factory_class` | Le nom de classe d'une `TransactionFactory` qui sera utilisée par l'API `Transaction` de Hibernate (la valeur par défaut est `JDBCTransactionFactory`). par ex.`classname.of.TransactionFactory`
`jta.UserTransaction` | Le nom JNDI utilisé par la `JTATransactionFactory` pour obtenir la `UserTransaction` JTA du serveur d'applications. par ex.`jndi/composite/name`
`hibernate.transaction.manager_lookup_class` | Le nom de la classe d'une `TransactionManagerLookup` - requise lorsque le cache de niveau JVM est activé ou lorsque l'on utilise un générateur hilo dans un environnement JTA. par ex.`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 Section 2.3, « Sessions contextuelles ». par ex.`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 Section 2.3, « Sessions contextuelles ». par ex.`true` | `false`

Tableau 3.7. Propriétés diverses

Nom de la propriété | Fonction
--- | ---
`hibernate.current_session_context_class` | Supply a custom strategy for the scoping of the "current" `Session`. See Section 2.3, « Sessions contextuelles » for more information about the built-in strategies. e.g. `jta` | `thread` | `managed` | `custom.Class`
`hibernate.query.factory_class` | Choisit l'implémentation du parseur de requête HQL. par ex.`org.hibernate.hql.ast.ASTQueryTranslatorFactory` ou `org.hibernate.hql.classic.ClassicQueryTranslatorFactory`
`hibernate.query.substitutions` | Lien entre les jetons de requêtes Hibernate et les jetons SQL (les jetons peuvent être des fonctions ou des noms textuels par exemple). par ex.`hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC`
`hibernate.hbm2ddl.auto` | Valide ou exporte automatiquement le schéma DDL vers la base de données lorsque la `SessionFactory` est créée. La valeur `create-drop` permet de supprimer le schéma de base de données lorsque la `SessionFactory` est fermée explicitement. par ex.`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. par ex.`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. Dialectes SQL

Il est recommandé de toujours positionner la propriété `hibernate.dialect` à la sous-classe de `org.hibernate.dialect.Dialect` appropriée à votre base de données. Si vous spécifiez un dialecte, Hibernate utilisera des valeurs adaptées pour certaines autres propriétés listées ci-dessus, vous évitant ainsi de l'effectuer à la main.

Tableau 3.8. Dialectes SQL de Hibernate (`hibernate.dialect`)

RDBMS | Dialecte
--- | ---
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 with MyISAM | `org.hibernate.dialect.MySQLMyISAMDialect`
Oracle (toutes versions) | `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. Chargement par jointure externe

Si votre base de données supporte les jointures externes de type ANSI, Oracle ou Sybase, le chargement par jointure externe devrait améliorer les performances en limitant le nombre d'aller-retour avec la base de données (la base de données effectuant donc potentiellement plus de travail). Le chargement par jointure ouverte permet à un graphe entier d'objets connectés par une relation plusieurs-à-un, un-à-plusieurs ou un-à-un d'être chargé en un seul SQL`SELECT`.

Le chargement par jointure ouverte peut être désactivé globalement en mettant la propriété `hibernate.max_fetch_depth` à `0`. Une valeur de `1` ou plus active le chargement par jointure externe pour les associations un-à-un et plusieurs-à-un qui ont été mappées avec `fetch="join"`.

See Section 21.1, « Stratégies de chargement » for more information.

### 3.4.3. Flux binaires

Oracle limite la taille d'un tableau d'`octets` qui peuvent être passés vers et à partir de son pilote JDBC. Si vous souhaitez utiliser des instances larges de type `binary` ou `serializable`, vous devez activer la propriété `hibernate.jdbc.use_streams_for_binary`. C'est une fonctionalité de niveau système uniquement.

### 3.4.4. Cache de second niveau et cache de requêtes

The properties prefixed by `hibernate.cache` allow you to use a process or cluster scoped second-level cache system with Hibernate. See the Section 21.2, « Le cache de second niveau » for more information.

### 3.4.5. Substitution dans le langage de requêtes

Vous pouvez définir de nouveaux jetons dans les requêtes Hibernate en utilisant `hibernate.query.substitutions`. Par exemple :

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

Cela signifierait que les jetons `true` et `false` seraient transformés par des entiers dans le SQL généré.

    hibernate.query.substitutions toLowercase=LOWER

Cela permettrait de renommer la fonction SQL `LOWER`.

### 3.4.6. Statistiques Hibernate

Si vous activez `hibernate.generate_statistics`, Hibernate fournira un certain nombre de métriques utiles pour régler les performances d'une application qui tourne via `SessionFactory.getStatistics()`. Hibernate peut aussi être configuré pour exposer ces statistiques via JMX. Lisez les Javadoc des interfaces dans le paquetage `org.hibernate.stats` pour plus d'informations.

## 3.5. Journalisation

Hibernate utilise Simple Logging Facade for Java (SLF4J) pour enregistrer divers événements du système. SLF4J peut diriger votre sortie de logging vers plusieurs structures de loggings (NOP, Simple, log4j version 1.2, JDK 1.4 logging, JCL or logback) suivant la liaison que vous choisirez. Pour pouvoir configurer votre logging, vous aurez besoin de `slf4j-api.jar` dans votre chemin de classe, ainsi que du fichier jar pour votre liaison préférée - `slf4j-log4j12.jar` pour Log4J. Voir la documentation SLF4J documentation pour davantage d'informations. Pour utiliser Log4j, vous aurez aussi besoin de mettre un fichier `log4j.properties` dans votre chemin de classe. Un exemple de fichier de propriétés est distribué avec Hibernate dans le répertoire `src/`.

Il est vivement recommandé de vous familiariser avec les messages des logs de Hibernate. Beaucoup de soin a été apporté pour donner le plus de détails possible sans les rendre illisibles. C'est un outil essentiel en cas de problèmes. Les catégories de logs les plus intéressantes sont les suivantes :

Tableau 3.9. Catégories de logs de Hibernate

Catégorie | Fonction
--- | ---
`org.hibernate.SQL` | Journalise toutes les requêtes SQL de type DML (gestion des données) qui sont exécutées
`org.hibernate.type` | Journalise tous les paramètres JDBC
`org.hibernate.tool.hbm2ddl` | Journalise toutes les requêtes SQL de type DDL (gestion de la structure de la base) qui sont exécutées
`org.hibernate.pretty` | Journalise l'état de toutes les entités (20 entités maximum) associées avec la session Hibernate au moment du flush
`org.hibernate.cache` | Journalise toute activité du cache de second niveau
`org.hibernate.transaction` | Journalise toute activité relative aux transactions
`org.hibernate.jdbc` | Journalise toute acquisition de ressource JDBC
`org.hibernate.hql.ast.AST` | Journalise l'arbre syntaxique des requêtes HQL et SQL durant l'analyse syntaxique des requêtes
`org.hibernate.secure` | Journalise toutes les demandes d'autorisation JAAS
`org.hibernate` | Journalise tout (beaucoup d'informations, mais très utile pour résoudre les problèmes).

Lorsque vous développez des applications avec Hibernate, vous devriez quasiment toujours travailler avec le niveau `debug` activé pour la catégorie `org.hibernate.SQL`, ou sinon avec la propriété `hibernate.show_sql` activée.

## 3.6. Sélectionne une `NamingStrategy` (stratégie de nommage)

L'interface `org.hibernate.cfg.NamingStrategy` vous permet de spécifier une "stratégie de nommage" des objets et éléments de la base de données.

Vous pouvez fournir des règles pour automatiquement générer les identifiants de base de données à partir des identifiants Java, ou transformer une colonne ou table "logique" donnée dans le fichier de mappage en une colonne ou table "physique". Cette fonctionnalité aide à réduire la verbosité de documents de mappage, en éliminant le bruit répétitif (les préfixes `TBL_` par exemple). La stratégie par défaut utilisée par Hibernate est assez minimale.

Vous pouvez définir une stratégie différente en appelant `Configuration.setNamingStrategy()` avant d'ajouter des mappages :

    SessionFactory sf = new Configuration()

        .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)

        .addFile("Item.hbm.xml")

        .addFile("Bid.hbm.xml")

        .buildSessionFactory();

`net.sf.hibernate.cfg.ImprovedNamingStrategy` est une stratégie fournie qui peut être utile comme point de départ de quelques applications.

## 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. Fichier de configuration XML

Une approche alternative est de spécifier toute la configuration dans un fichier nommé `hibernate.cfg.xml`. Ce fichier peut être utilisé à la place du fichier `hibernate.properties`, voire même peut servir à surcharger les propriétés si les deux fichiers sont présents.

Le fichier de configuration XML doit par défaut se placer à la racine du `CLASSPATH`. En voici un exemple :

    <?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>

Comme vous pouvez le constater, l'avantage de cette approche est l'externalisation des noms des fichiers de mappage de la configuration. Le fichier `hibernate.cfg.xml` est également plus pratique quand on commence à régler le cache d'Hibernate. Notez que vous pouvez choisir entre utiliser `hibernate.properties` ou `hibernate.cfg.xml`, les deux sont équivalents, sauf en ce qui concerne les bénéfices de l'utilisation de la syntaxe XML mentionnés ci-dessus.

Avec la configuration XML, démarrer Hibernate devient donc aussi simple que ceci :

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

Vous pouvez choisir un fichier de configuration XML différent en utilisant :

    SessionFactory sf = new Configuration()

        .configure("catdb.cfg.xml")

        .buildSessionFactory();

## 3.9. Java EE Application Server integration

Hibernate possède les points d'intégration suivants pour l'infrastructure J2EE :

- Source de données gérée par le conteneur : Hibernate peut utiliser des connexions JDBC gérées par le conteneur et fournies par l'intermédiaire de JNDI. Souvent, un `TransactionManager` compatible JTA et un `ResourceManager` s'occupent de la gestion des transactions (CMT). Ils sont conçus en particulier pour gérer des transactions distribuées sur plusieurs sources de données. Vous pouvez biensûr également définir les limites des transactions dans votre programme (BMT) ou vous pouvez par ailleurs utiliser l'API optionnelle `Transaction` de Hibernate qui vous garantira la portabilité de votre code entre plusieurs serveurs d'application.

- Association JNDI automatique: Hibernate peut associer sa `SessionFactory` à JNDI après le démarrage.

- Association de la Session à JTA: la `Session` Hibernate peut être automatiquement associée à la portée des transactions JTA si vous utilisez les EJB. Vous avez juste à récupérer la `SessionFactory` depuis JNDI et à récupérer la `Session` courante. Hibernate s'occupe de vider et fermer la `Session` lorsque votre transaction JTA se termine. La démarcation des transactions se fait de manière déclarative (CMT) ou de façon programmatique (BMT/UserTransaction).

- Déploiement JMX :Si vous avez un serveur d'applications compatible JMX (JBoss AS par exemple), vous pouvez choisir de déployer Hibernate en tant que MBean géré par le serveur. Cela vous évite de coder la ligne de démarrage qui permet de construire la `SessionFactory` depuis la `Configuration`. Le conteneur va démarrer votre `HibernateService`, et va idéalement s'occuper des dépendances entre les services (la source de données doit être disponible avant le démarrage de Hibernate, etc).

En fonction de votre environnement, vous mettrez l'option de configuration `hibernate.connection.aggressive_release` à true si le serveur d'applications affiche des exceptions de type "connection containment".

### 3.9.1. Configuration de la stratégie transactionnelle

L'API de la `Session` Hibernate est indépendante de tout système de démarcation des transactions, présent dans votre architecture. Si vous laissez Hibernate utiliser l'API JDBC directement via un pool de connexion, vous commencerez et terminerez vos transactions en appelant l'API JDBC. Si votre application tourne à l'intérieur d'un serveur d'applications J2EE, vous utiliserez peut être les transactions gérées par les beans (BMT) et vous appellerez l'API JTA et `UserTransaction` lorsque cela est nécessaire.

Pour conserver votre code portable entre ces deux environnements (et d'autres), nous vous recommandons d'utiliser l'API optionnelle `Transaction` d'Hibernate, qui encapsule et masque le système de transaction sous-jacent. Pour cela, vous devez préciser une classe de fabrique d'instances de `Transaction` en positionnant la propriété de configuration `hibernate.transaction.factory_class`.

Il existe trois choix standards (intégrés) :

`org.hibernate.transaction.JDBCTransactionFactory`

  délègue aux transactions de la base de données (JDBC) (valeur par défaut).

`org.hibernate.transaction.JTATransactionFactory`

  délègue à CMT si une transaction existante est sous ce contexte (par ex : méthode d'un EJB session), sinon une nouvelle transaction est entamée et une transaction gérée par le bean est utilisée.

`org.hibernate.transaction.CMTTransactionFactory`

  délègue aux transactions JTA gérées par le conteneur

Vous pouvez également définir vos propres stratégies transactionnelles (pour un service de transaction CORBA par exemple).

Certaines fonctionnalités de Hibernate (c'est-à-dire le cache de second niveau, l'association automatique des Sessions à JTA, etc.) nécessitent l'accès au `TransactionManager` JTA dans un environnement géré. Dans un serveur d'applications, vous devez indiquer comment Hibernate peut obtenir une référence vers le `TransactionManager`, car J2EE ne fournit pas un seul mécanisme standard.

Tableau 3.10. TransactionManagers JTA

Fabrique de transaction | Serveur d'applications
--- | ---
`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` associée au JNDI

Une `SessionFactory` Hibernate associée au JNDI peut simplifier l'accès à la fabrique et donc la création de nouvelles `Session` s. Notez que cela n'est pas lié avec les `Datasource` associées au JNDI, elles utilisent juste le même registre !

Si vous désirez associer la `SessionFactory` à un nom JNDI, spécifiez un nom (par ex. `java:hibernate/SessionFactory`) en utilisant la propriété `hibernate.session_factory_name`. Si cette propriété est omise, la `SessionFactory` ne sera pas associée au JNDI (c'est particulièrement pratique dans les environnements ayant une implémentation JNDI par défaut en lecture seule, comme c'est le cas pour Tomcat).

Lorsqu'il associe la `SessionFactory` au JNDI, Hibernate utilisera les valeurs de `hibernate.jndi.url`, `hibernate.jndi.class` pour instancier un contexte d'initialisation. S'ils ne sont pas spécifiés, l'`InitialContext` par défaut sera utilisé.

Hibernate va automatiquement placer la `SessionFactory` dans JNDI après avoir appelé `cfg.buildSessionFactory()`. Cela signifie que vous devez avoir cet appel dans un code de démarrage (ou dans une classe utilitaire) dans votre application sauf si vous utilisez le déploiement JMX avec le service `HibernateService` présenté plus tard dans ce document.

Si vous utilisez `SessionFactory` JNDI, un EJB ou n'importe quelle autre classe peut obtenir la `SessionFactory` en utilisant une recherche 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. Gestion du contexte de la session courante à JTA

The easiest way to handle `Sessions` and transactions is Hibernate's automatic "current" `Session` management. For a discussion of contextual sessions see Section 2.3, « Sessions contextuelles ». 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. Déploiement JMX

La ligne `cfg.buildSessionFactory()` doit toujours être exécutée quelque part pour obtenir une `SessionFactory` dans JNDI. Vous pouvez faire cela dans un bloc d'initialisation `static` (comme celui qui se trouve dans la classe `HibernateUtil`) ou vous pouvez déployer Hibernate en temps que service géré.

Hibernate est distribué avec `org.hibernate.jmx.HibernateService` pour le déploiement sur un serveur d'applications avec le support de JMX comme JBoss AS. Le déploiement et la configuration sont spécifiques à chaque vendeur. Voici un fichier `jboss-service.xml` d'exemple pour 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>

Ce fichier est déployé dans un répertoire `META-INF` et est empaqueté dans un fichier JAR avec l'extension `.sar` (service archive). Vous devez également empaqueter Hibernate, les librairies tierces requises, vos classes persistantes compilées et vos fichiers de mappage dans la même archive. Vos beans entreprise (souvent des EJB session) peuvent rester dans leur propre fichier JAR mais vous pouvez inclure ce fichier JAR dans le jar principal du service pour avoir une seule unité déployable à chaud. Vous pouvez consulter la documentation de JBoss AS pour plus d'informations sur les services JMX et le déploiement des EJB.

Copyright © 2004 Red Hat, Inc.

- PrécédentChapitre 2. Architecture
- Niveau supérieur
- Sommaire
- SuivantChapitre 4. Classes persistantes