persistence.xml: CONSTRAINTS INITIALLY DEFERRABLE
Bonjour,
Mon problème est le suivant:
J'ai un schema qui se crée lorsque je déploie mes EJB dans Glassfish.
J'ai besoin de désactiver les contraintes afin d'insérer des jeux de tests (qui sont eux générés dans un ordre qui ne tient pas compte des contraintes, d'où le besoin).
Afin de faire ca sans tenir compte des noms des contraintes, j'ai trouvé qu'une solution était d'utiliser la commande SET CONSTRAINTS ALL DEFERRED (dans postgresql), et de passer le tout dans une section BEGIN/ COMMIT (ce qui contourne l'autocommit de postgresql).
Or les contraintes ne peuvent être mises à DEFERRED que si elles sont crées en statut INITIALLY DEFERRABLE.
Leur création étant effectuée par TopLink (qui créé les contraintes en NOT DEFERRABLE par défaut).
J'ai beaucoup de mal à trouver des réponses claires sur le net, la majorité des réponses concernent OPENJPA et non TopLink.
Quelqu'un pourrait il m'aider svp?
Merci par avance.
TopLink/Postgresql CONSTRAINTS DEFERRABLE
Adéfaut de réponses, je remercie quand même les personnes qui m'ont aidées dans mes recherches (Frédéric Brouard de SQLPro notammenthttp://sqlpro.developpez.com) et je vais vous faire part de mes conclusions.
L'environnement était le suivant:
Des EJB déployés dans openEJB,
TopLink afin d'assurer la persistence
Une base Postgresql 8.3
Problème rencontré:
Comment executer un script d'INSERT quand celui-ci est autogénéré dans un ordre ne respectant pas les contraintes entre les tables, générées par TopLink lors du déploiement des EJB?
Solution trouvée:
La solution optimale est d'effectuer l'opération suivante: désactiver les contraintes sur le schéma, exécuter le script d'insert, remettre les contraintes.
Si cette opération est manifestement native avec Oracle, sous Postgresql ca se passe différemment. On ne peut pas "désactiver" les contraintes, mais les "déférer" (leur application ne prendra effet qu'avec un commit).
Concrètement:
- Placez vos requêtes dans une section Begin/commit (postgresql ne supportant plus le set autocommit off, les ordres passés après le BEGIN ne seront appliqués qu'avec la commande COMMIT).
- inscrivez l'ordre SET CONSTRAINTS ALL DEFERRED;
- Inscrivez vos requêtes d'INSERT.
- exécutez
Les INSERT se feront qu'ils respectent ou non les contraintes sur la/les tables concernées, en revanche le respect de celles-ci ne sera vérifié que lors du COMMIT. Vous comprenez ainsi que l'on peut insérer des données dans un schéma dans l'ordre que l'on souhaite.
NEANMOINS LE PROBLEME EST ET DEMEURE...:
Pour que la commande SET CONSTRAINTS ALL DEFERRED fonctionne, il faut que les contraintes aient été créées selon un des trois modes suivants:
- DEFERRABLE: la contrainte opère après que l'ordre SQL qui la met en cause se soit appliqué au moment de la validation de la transaction
- INITIALY DEFERRED: La contrainte sera déférée à l'initiation de chaque transaction sauf si elle est créée en NOT DEFERRABLE. En d'autres termes elle est vérifiée en fin de transaction
- INITIALY IMMEDIATE: La contrainte sera appliquée immédiatement à l'initiation de la transaction.
Or, TopLink crée manifestement les contraintes en mode...
- NOT DEFERRABLE: LA contrainte opère dés que l'ordre SQL qui la met en cause est appliqué. Elle ne pourra jamais être déférée.
(sources http://sqlpro.developpez.com)
Ma recherche portait donc sur "Comment instantier la création des contraintes par TopLink en un de ces 3 modes (notemment DEFERRABLE bien sûr)".
Il se trouve que manifestement il n'est pas possible (ou je suis passé à coté et dans ce cas je suis preneur de la solution) de modifier le mode de création avec TopLink.
Avec cet environnement technique il ne vous reste donc que les deux solutions suivantes:
- Générer vos insert dans un ordre respectant les contraintes sur les tables.
- Dropper les contraintes (alter table...), effectuer les insert puis recréer les contraintes. Mais cette solution nécesssite bien sûr d'avoir connaissance du nom des contraintes appliquées sur les tables et de tenir à jour vos scripts...
Voilà pour moi, si vous avez la solution, je suis preneur!
Merci par avance.
TopLink/Postgresql CONSTRAINTS DEFERRABLE
Oui justement c'est ce que j'aimerais bien faire.
Mais je ne sais pas vraiment où chercher dans le code de TopLink afin de modifier le NO DEFERRABLE.
Citation:
Envoyé par
JeitEmgie
je ne peux pas jurer que cela est faisable avec TopLink mais avec Hibernate je procéderais de la façon suivante :
subclasser le dialect PostgreSQL
overwrite des méthodes qui génèrent le code qui ne me convient pas
spécifier mon custom dialect comme étant celui à utiliser
(si réellement il n'y aucun paramètre spécifique pour changer ce comportement : ce que je vérifierais d'abord dans le code source… là où le INITIALLY DEFERRABLE est généré… ce qui de toute façon est nécessaire pour faire le bon overwrite…)