Hibernate.orgCommunity Documentation
La portabilité des bases de données est un des atouts qui sont mis en avant pour vendre Hibernate (et plus largement le mappage objet/relationnel dans son ensemble). Il pourrait s'agir d'un utilisateur IT interne qui migre d'une base de données de fournisseur vers une autre, ou il pourrait s'agir d'un framework ou d'une application déployable consommant Hibernate pour cibler simultanément plusieurs produits de base de données par leurs utilisateurs. Quel que soit le scénario exact, l'idée de base est que vous souhaitez que HIBERNATE vous permettre d'exécuter avec un certain nombre de bases de données sans modifications à votre code et idéalement sans modifications des métadonnées de mappage.
La première ligne de la portabilité d'Hibernate est le dialecte, qui est une spécialisation du contrat org.Hibernate.dialect.dialect
. Un dialecte encapsule toutes les différences selon lesquelles Hibernate doit communiquer avec une base de données particulière pour accomplir certaines tâches comme l'obtention d'une valeur de la séquence ou de structuration d'une requête SELECT. Hibernate regroupe un large éventail de dialectes pour la plupart des bases de données les plus communes. Si vous trouvez que votre base de données particulière n'en fait pas partie, il n'est pas difficile d'écrire votre propre dialecte.
À l'origine, Hibernate exigeait toujours que les utilisateurs spécifient quel dialecte utiliser. Dans le cas des utilisateurs qui cherchent à cibler simultanément plusieurs bases de données avec leur version, c'était problématique. Généralement cela amenait leurs utilisateurs à configurer le dialecte Hibernate ou à définir leur propre méthode de définition de cette valeur.
A partir de la version 3.2, Hibernate a introduit la détection automatiquement du dialecte à utiliser basé sur les Java.SQL.DatabaseMetaData
obtenues à partir d'un Java.SQL.Connexion
vers cette base de données. C'était beaucoup mieux, sauf que cette résolution a été limitée aux bases de données déjà connues d'Hibernate et elle n'était ni configurable, ni remplaçable.
Starting with version 3.3, Hibernate has a fare more powerful way to automatically determine which dialect to should be used by relying on a series of delegates which implement the org.hibernate.dialect.resolver.DialectResolver
which defines only a single method:
<!-- <br/> --><span class="java_keyword">public</span><!-- <br/> --><span class="java_plain"> </span><!-- <br/> --><span class="java_type">Dialect</span><!-- <br/> --><span class="java_plain"> resolveDialect</span><!-- <br/> --><span class="java_separator">(</span><!-- <br/> --><span class="java_type">DatabaseMetaData</span><!-- <br/> --><span class="java_plain"> metaData</span><!-- <br/> --><span class="java_separator">)</span><!-- <br/> --><span class="java_plain"> </span><!-- <br/> --><span class="java_keyword">throws</span><!-- <br/> --><span class="java_plain"> </span><!-- <br/> --><span class="java_type">JDBCConnectionException</span>
. The basic contract here is that if the resolver 'understands' the given database metadata then it returns the corresponding Dialect; if not it returns null and the process continues to the next resolver. The signature also identifies org.hibernate.exception.JDBCConnectionException
as possibly being thrown. A JDBCConnectionException here is interpreted to imply a "non transient" (aka non-recoverable) connection problem and is used to indicate an immediate stop to resolution attempts. All other exceptions result in a warning and continuing on to the next resolver.
Le bon côté de ces outils de résolution, c'est que les utilisateurs peuvent également enregistrer leurs propres outils de résolution personnalisés, qui seront traités avant les résolveurs Hibernate intégrés. Cette option peut être utile dans un certain nombre de situations différentes : elle permet une intégration aisée pour la détection automatique des dialectes au-delà de ceux qui sont livrés avec Hibernate lui-même ; elle vous permet de spécifier d'utiliser un dialecte personnalisé lorsqu'une base de données particulière est reconnue ; etc.. Pour enregistrer un ou plusieurs outils de résolution, il vous suffit de les spécifier (séparés par des virgules, des onglets ou des espaces) à l'aide du paramètre de configuration 'hibernate.dialect_resolvers' (voir la constante DIALECT_RESOLVERS
sur cfg.Environment org.Hibernate.
).
When considering portability between databases, another important decision is selecting the identifier generation stratagy you want to use. Originally Hibernate provided the native generator for this purpose, which was intended to select between a sequence, identity, or table strategy depending on the capability of the underlying database. However, an insidious implication of this approach comes about when targtetting some databases which support identity generation and some which do not. identity generation relies on the SQL definition of an IDENTITY (or auto-increment) column to manage the identifier value; it is what is known as a post-insert generation strategy becauase the insert must actually happen before we can know the identifier value. Because Hibernate relies on this identifier value to uniquely reference entities within a persistence context it must then issue the insert immediately when the users requests the entitiy be associated with the session (like via save() e.g.) regardless of current transactional semantics.
Hibernate was changed slightly once the implication of this was better understood so that the insert is delayed in cases where that is feasible.
The underlying issue is that the actual semanctics of the application itself changes in these cases.
Starting with version 3.2.3, Hibernate comes with a set of enhanced identifier generators targetting portability in a much different way.
There are specifically 2 bundled enhancedgenerators:
org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.id.enhanced.TableGenerator
The idea behind these generators is to port the actual semantics of the identifer value generation to the different databases. For example, the org.hibernate.id.enhanced.SequenceStyleGenerator
mimics the behavior of a sequence on databases which do not support sequences by using a table.
This is an area in Hibernate in need of improvement. In terms of portability concerns, this function handling currently works pretty well from HQL; however, it is quite lacking in all other aspects.
SQL functions can be referenced in many ways by users. However, not all databases support the same set of functions. Hibernate, provides a means of mapping a logical function name to a delegate which knows how to render that particular function, perhaps even using a totally different physical function call.
Techniquement, cet enregistrement de la fonction est géré par le biais de la classe hibernate.dialect.function.SQLFunctionRegistry org.
qui est destinée à permettre aux utilisateurs de fournir des définitions de fonction personnalisée sans avoir à fournir un dialecte personnalisé. Ce comportement spécifique n'est pas encore entièrement terminé.
Il est mis en oeuvre de telle sorte que les utilisateurs peuvent enregistrer des fonctions par programmation avec org.Hibernate.cfg.Configuration
et ces fonctions seront reconnues pour HQL.
Copyright © 2004 Red Hat, Inc.