Hibernate sur Oracle et SQL Server

J'introduis une couche DAO dans notre application qui fonctionne actuellement sur SQL Server car j'ai besoin de la porter sur Oracle.

J'aimerais utiliser Hibernate et écrire une fabrique (ou utiliser une dependency injections) pour choisir les DAO corrects en fonction de la configuration du deployment. Quelles sont les meilleures pratiques dans ce cas? Dois-je avoir deux packages avec différents files hibernate.cfg.xml et * .hbm.xml et les choisir en conséquence dans mon usine? Est-il possible que mes DAO fonctionnent correctement avec les deux SGBD sans (trop) tracas?

En supposant que les noms de table et les colonnes sont les mêmes entre les deux, vous devriez pouvoir utiliser les mêmes files hbm.xml . Cependant, vous devrez certainement fournir une valeur de configuration Hibernate différente ( hibernate.cfg.xml ), car vous devrez changer le dialecte d'Hibernate de SQLServer à Oracle.

S'il existe de légères différences de nom entre les deux, je créerais deux sets de files de mappage – un par server de database – et les regrouperais dans des files JAR distincts (tels que yourproject-sqlserver-mappings.jar et yourproject-oracle-mappings.jar ), et déployer l'application avec un file JAR ou l'autre en fonction de l'environnement.

Je l'ai fait pour un client il y a un certain time – au deployment en fonction d'une propriété définie dans un file production.properties j'ai changé le hibernate.dialect dans le file cfg en utilisant Ant (vous pouvez utiliser n'importe quel transformateur xml). Cependant, cela ne fonctionnerait que si le code Hibernate est btw sans faille entre les DBs, c.-à-d. Aucun appel de fonction spécifique à db, etc. HQL / JPAQL a des appels de fonction standard qui aident à cet égard.

Si les implémentations db doivent nécessairement être différentes, vous devrez faire quelque chose comme @matt.

J'ai travaillé sur une application qui supporte beaucoup de bases de données (Oracle, Informix, SQL Server, MySQL). Nous avons un file de configuration et un set de mappages. Nous utilisons jndi pour la connection à la database afin que nous n'ayons pas à traiter avec différentes URL de connection dans l'application. Lorsque nous initialisons SessionFactory, nous avons une méthode qui déduit le type de database de la connection sous-jacente. Par exemple, obtenez manuellement une connection via JNDI, puis utilisez connection.getMetaData (). GetDatabaseProductName () pour connaître la database. Vous pouvez également utiliser une variable d'environnement conteneur pour le définir explicitement. Définissez ensuite le dialecte en utilisant configuration.setProperty (Environment.DIALECT, deducedDialect) et initialisez le SessionFactory comme d'habitude.

Certaines choses que vous avez à faire:

  • Génération de key primaire Nous utilisons une version personnalisée de la stratégie TableGenerator donc nous avons une table key avec des colonnes pour le nom de la table et la key suivante. De cette façon, chaque database peut utiliser la même stratégie plutôt que la séquence dans Oracle, natif pour SQL Server, etc.
  • Fonctions spécifiques aux bases de données. Nous les évitons quand c'est possible. Les dialectes Hibernate gèrent les plus communs. De time en time, nous devrons append les nôtres à nos classs dialectales personnalisées. Par exemple, l'arithmétique des dates est assez non standard, nous allons donc simplement créer un nom de fonction et le mapper à la manière de chaque database.
  • Génération de schéma – nous utilisons la class de génération de schéma Hibernate – elle travaille avec les dialectes pour créer le DDL correct pour chaque type de database et force la database à correspondre aux mappages. Vous devez être conscient des mots-keys pour chaque database, par exemple ne pas essayer d'avoir une table USER dans Oracle (les USERS fonctionneront), ou une table TRANSLATION dans MySQL.

Il y a un tableau qui trace les différences entre Oracle et SQLServer ici: http://psoug.org/reference/sqlserver.html

À mon avis les plus grands pièges sont: 1) Dates. Les fonctions et la mécanique sont complètement différentes. Vous devrez utiliser un code différent pour chaque DB. 2) Génération de keys – Oracle et SQLServer utilisent des mécanismes différents et si vous essayez d'éviter la génération "native" en ayant votre propre table de keys – eh bien, vous venez de sérialiser complètement tous vos "inserts". Pas bon pour la performance. 3) La concurrency / locking est un peu différent. Les parties du code sensibles aux performances seront probablement différentes pour chaque database. 4) Oracle est sensible à la casse, SQLServer ne l'est pas. Vous devez être prudent avec ça.

Il y en a beaucoup plus 🙂 L'écriture de code SQL qui s'exécutera sur deux DB est difficile. Faire vite peut parfois sembler presque impossible.