Bonjour,
J'ai une application qui utilise Spring 2.5.2 et Hibernate 3.2.6 pour la connexion à la base de données.
Je dois me connecter à un schéma précis sur ma bases de données, mais au runtime de l'application, ce schéma peut changer. Mais quoiqu'il en soit, je ne me connecte jamais qu'à un seul schéma à la fois (ouf !)
Les tables et colonnes sur lesquels je travaille existent dans tous les schémas accessibles, mais pas forcément sous les mêmes noms, en particulier pour les tables, qui n'ont jamais le même nom !
Globalement, j'ai réussi à peu près à m'en sortir, mais je trouve l'ensemble très fastidieux, car il y a énormément de redondances.
Prennons un exemple plus concret. Je dois gérer des débiteurs (debtors), j'ai donc une table T_DEBTOR.
Si on se limite à 2 schémas (mais dans mon application, je serais plutôt entre 5 et 20), je vais donc avoir 2 tables : T_DEBTOR_ONE et T_DEBTOR_TWO.
Dans mon code Java, idéalement, je souhaiterais n'avoir qu'à gérer une classe, Debtor.
Comme je travaille avec Hibernate annotations, je dois toutefois créer des sous classes : DebtorOne et DebtorTwo, chacune correspondant à une entité dans le schéma correspondant.
Voici en gros ce que donne le code Java de ma classe mère (j'utilise l'annotation @MappedSuperclass) :
Et dans ma classe DebtorOne (qui sera pareil que DebtorTwo) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 @MappedSuperclass public class Debtor { @Id @Column(name = "IDDEBTOR") protected String idDebtor; // Avec les getter et setter ... }
Maintenant, du côté de mon DAO, je veux récupérer l'ensemble des debtors. Une requête de ce type ne fonctionnera pas :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 @Entity @Table(name = "DEBTOR_ONE") public class DebtorOne extends Debtor { ...
En effet, vu comme ça, Hibernate se plaind de ne pas connaître l'entité Debtor.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 public List<Debtor> findAllDebtors() { return (List<Debtor>) em.createQuery("select d from Debtor d").getResultList(); }
Du coup, je suis obligé de tricher en créant dans mes entités des NamedQueries :
(pour être tout à fait exact, les noms des NamedQueries varient selon le schéma de destination, mais ça, j'arrive à le gérer sans problème)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 @Entity @Table(name = "T_DEBTOR_ONE") @NamedNativeQueries( { @NamedNativeQuery(name = "findAllDebtors", query = "select d from DebtorOne d") }) public class DebtorOne implements Debtor { ...
Du coup, dans mon DAO, j'ai ceci :
Alors là, ça marche, même si c'est moyennement beau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 @SuppressWarnings("unchecked") public List<Debtor> findAllDebtors() { Query q = em.createNamedQuery("findAllDebtors"); return (List<Debtor>) q.getResultList(); }
Mais les choses se corsent maintenant si je veux persister un object dans mon DAO :
Là, j'ai un problème :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Transactional public void save(Debtor debtor) { em.persist(debtor); }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 // Ce code marche Debtor one = new DebtorOne(); debtorDao.save(one); // Celui-là non ! Debtor two = new Debtor(); debtorDao.save(two);
J'ai pensé à quelques pistes pour résoudre ce problème :
1. Créer des factories, de façons à faire ceci :
Ca devrait marcher mais c'est vraiment lourd je trouve de trainer toutes ces usines...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 Debtor one = new DebtorFactory.createDebtor(); // Ici, one pourrait être un DebtorOne ou un DebtorTwo, mais pas un Debtor "tout court" et donc Hibernate serait content ! debtorDao.save(one);
2. Oublier les annotations et passer par la configuration XML. En effet, si au changement du schéma je recharge également toute ma configuration XML, je devrais pouvoir m'en sortir avec les classes de bases (i.e. Debtor uniquement, sans les DebtorXXX).
3. Idéalement, j'aimerais pouvoir changer les paramètres des annotations Hibernate au runtime. Ainsi, avoir juste une classe Debtor :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 @Entity @Table(name = "La magie intervient ici") @NamedNativeQueries( { @NamedNativeQuery(name = "findAllDebtors", query = "select d from Debtor d") }) public class Debtor { ...
Mes questions :
Que pensez-vous de ma façon de résoudre le problème ?
Comment faire pour rendre les choses plus faciles ?
Puis-je m'en sortir simplement en conservant les Hibernate annotations, ou dois-je absolument passer par la configuration XML.
Merci d'avance.
Partager