EJB select plante avec ORA constraint violation - Java - Programmation
Marsh Posté le 21-08-2006 à 18:21:34
hum, si tu commençais par regarder la gueule de l'sql qui est executé?
Marsh Posté le 21-08-2006 à 19:14:50
Mé Toutafé
Bien que la séquence soit correcte dans le log applicatif, les traces JDBC de Weblogic ne correspondent pas.
Log applicatif:
- création de l'entité SU;
- création de l'entité BU;
- ejb-select
Weblogic JDBC logging:
- Création de l'entité SU uniquement;
- va mourir sur ejb-select
Après la création de SU, je fais un output de la PK de l'entité créée (que j'obtiens de la local reference), et je pousse même le vice jusqu'à faire un findByPK qui réussit.
Similaire dans d'autres cas (où le log JDBC montre p.e. un SELECT d'une séquence Oracle, mais sans l'utiliser ensuite pour créer le record, passant directement à l'INSERT du record child).
Pq y fait ça ?
Marsh Posté le 22-08-2006 à 14:29:43
Ch'tit up
Marsh Posté le 23-08-2006 à 15:54:36
Ca n'inspire pas les foules...
Les joies du J2EE.
Marsh Posté le 24-08-2006 à 14:02:55
[Mode luser de la cat PHP on]
Mé je croyais que s'été un forum d'entraide et vous ne m'aider pas
[Mode luser de la cat PHP off]
Sérieusement, je suis en contact avec le support BEA, mais pour ceux qui ont déjà eu cette expérience, c'est pas la joie.
On me propose une première solution:
Au passage, cette dernière modification est une horreur sans nom : il s'agit de dupliquer le finder du ejb-jar dans ejb-cmp-weblogic... A la sauce Weblogic (les balises sont différentes). Super la double maintenance.
De toute façon, cela ne marche pas.
Qqn a déjà essayé de modifier ces settings ?
2è sol proposée, pire que la première :
Commencer à modifier les contraintes alors qu'elles ne sont pas nommées (du bon boulot), je dis
Marsh Posté le 24-08-2006 à 14:29:01
sircam a écrit : L'application sur laquelle je bosse (Weblogic 8.1 SP5, Oracle 9i) plante sur un EJB select avec une SQLException renvoyant une erreur Oracle ORA-02291 : "constraint violation - parent key not found". |
En gros il doit s'agir d'un problème d' "ordre de création" de clés primaires et étrangères entre tables avec des collections interdépendantes. Ca arrive très souvent dès qu'on fait de la persistence, en JDO entre autres. Une table refuse d'insérer une clé étrangère (vers une collection dépendante) parce que la clé primaire correspondante pour l'élément lié à insérer n'existe pas encore dans l'autre table.
En Oracle il faut utiliser les "deferred constraints" : http://www.remote-dba.cc/t_garmany [...] raints.htm pour éviter le problème, ça permet de ne vérifier les contraintes d'intégrité qu'au commit final.
Marsh Posté le 24-08-2006 à 16:28:27
Mais pourquoi n'y a-t-il pas moyen de demander à WL d'envoyer les queries dans l'ordre ? Je pige pas pq seulement 2 ou 3 des 4 inserts sont exécutés AVANT le finder d'après le log JDBC, alors que le code les exécute comme il le faut.
La doc de WL est pourtant claire : avec include-update, WL flush les pending inserts avant d'exécuter le finder. Avec order-database-operations, les INSERT sont exécutés dans le bon ordre, à supposer que WL décide par défaut de les envoyer dans le désordre (à ce sujet, pq ne pas les exécuter dans le bon ordre directement )
Or, ni l'un ni l'autre ne fonctionne. Soit j'ai loupé qq chose, soit c'est du khakha en boîte.
Rendre les contraintes deferrables, c'est pas évident : la DB tourne en production et, grâce à un bon boulot du DBA, les contraintes ne sont pas nommées. Chaque schema (PROD, customer QA, internal QA, DEV, ...) possède donc un nom de contrainte différent, autogénéré. Pas possible de scripter cela.
Oui, je sais, une horreur.
Rendre les contraintes deferrables, c'est un peu just dans le cas présent, d'autant qu'il n'y aucune raison "valable" : j'entends par là que si j'exécute à la main les queries, ça se passera tjs correctement.
Citation : Une table refuse d'insérer une clé étrangère (vers une collection dépendante) parce que la clé primaire correspondante pour l'élément lié à insérer n'existe pas encore dans l'autre table. |
OK si on insère dans le désordre... mais ici, pq ça se passe dans le désordre, justement ?
Je veux bien admettre que ça puisse marcher, mais demander de modifier la DB parce que ça coince au niveau WL, c'est assez insupportable, et ça semble inadapté : en l'occurence, on (== le code) insère bien record après record sans jamais violer de contrainte. La violation survient à cause d'un comportement indésirable du client de la DB (en l'occurence, Weblogic).
Tout cela est fort peu satisfaisant (pas ta réponse, mais cet état de fait).
Merci pour ta réponse!
Marsh Posté le 24-08-2006 à 22:18:43
sircam a écrit : Rendre les contraintes deferrables, c'est pas évident : la DB tourne en production et, grâce à un bon boulot du DBA, les contraintes ne sont pas nommées. Chaque schema (PROD, customer QA, internal QA, DEV, ...) possède donc un nom de contrainte différent, autogénéré. Pas possible de scripter cela. |
Je dirais que tu as 3 options :
_ Rendre les contraintes deferrables, ce n'est qu'un paramètre de la base de données, sûrement le plus simple, et ça reste propre.
_ commiter plus souvent, les PK collections annexes d'abord avant les FK correspondantes (une Personne a une Collection de Skills, commite les Skills tout de suite dans ton code avant la Personne, comme ça plus de soucis car chaque Skill associé (PK) existera bien lorsque ceux (FK) de la Personne le seront).
_ utiliser un gestionnaire de persistance comme JDO ou Hibernate qui se charge de ce genre de problèmes.
Ne cherche pas trop à paufiner non plus, les problèmes de persistence ça peut tourner facilement au cauchemar, prends le plus simple.
Marsh Posté le 25-08-2006 à 10:47:00
Bon... Je vais voir si je me résouds à la solution 1°.
Le fait de devoir modifier les contraintes de la DB parce que le serveur applicatif ne fait pas son boulot dans l'ordre (ou parce que je ne parviens pas à lui faire faire), c'est pour le moins déplaisant.
Je vais vérifier si par hasard les contraintes sont deferrables sur la DB prod. Peut-être nous a-t-on menti.
2° n'est pas une option : il s'agit ici d'une unité logique de travail. Si on plante en cours de route, j'entends bien que les INSERTs précédents soient rollabackés! A ce train là, je peux théoriquement commiter après chaque INSERT ou UPDATE pour m'assurer de l'absence de viloation.
3° Oh non, on est grillaid. C'est une application legacy J2EE, une véritable pièce archéologique et ce problème se manifeste sur du code existant depuis belle lurette, alors qu'on livre cette version à date raprochée. Passer à Hibernate quand on a bien absusé de l'API intrusive des entity beans, c'est pas trivial. On racontait à l'époque que les entity beans, c'était juste des interfaces et qu'on pouvait théoriquement changer l'implémentation derrière, et des Anciens y ont cru. Mais on a découvert la vérité plus tard. Trop tard. Les entity beans EJB 2.1, cai la malle.
Tu dis que rendre les contraintes deferrables n'est qu'un paramètre. Ca me dit qq chose, mais je me demande si ce n'était pas au niveau de la session. A approfondir, car un ALTER de chaque contrainte individuelle n'est pas envisageable.
Merci en tout cas. Je tiendrai mon nombreux public au courant de l'évolution, si les Indiens de BEA parviennent à m'expliquer pq les settings initiaux (include-updates et toussa) ne donnent pas le résultat escompté.
Marsh Posté le 25-08-2006 à 12:12:59
Je ne sais pas si les infos sont exactes, mais ce thread semble intéressant:
http://forums.bea.com/bea/message. [...] 3&tstart=0
include-updates serait True par défaut.
Ce que j'adore (entre autre) avec la doc Weblogic, c'est qu'en général, les valeurs par défaut ne sont pas spécifiées. Du bon boulot. Le meilleur étant la javadoc JMX dans 6.1 : des dizaines de méthodes documentées "TODO" ou reproduisant le nom de la méthode en guise de doc.
Marsh Posté le 25-08-2006 à 15:55:14
sircam a écrit : Je ne sais pas si les infos sont exactes, mais ce thread semble intéressant: |
C'est parce que la doc est générée automatiquement... Sinon j'ai tout juste parcouru (viteuf, chui charette today...) ton problème, ça ressemble à une problématique BDD plutôt que java. Tu devrais utiliser les optimist locks, c'est le mieux pour éviter ce genre de problème (n'ayant pas tout lu j'espère ne pas être trop à côté de la plaque...)
Marsh Posté le 25-08-2006 à 16:45:02
Calahad a écrit : C'est parce que la doc est générée automatiquement...) |
Beh ouais, faut que l'ingénieur indien payé des cawètes tape la javadoc qui va bien dans le code, hein. C'est ça le problème.
Calahad a écrit : Sinon j'ai tout juste parcouru (viteuf, chui charette today...) ton problème, ça ressemble à une problématique BDD plutôt que java. Tu devrais utiliser les optimist locks, c'est le mieux pour éviter ce genre de problème (n'ayant pas tout lu j'espère ne pas être trop à côté de la plaque...) |
AMHA, je ne pense pas que cela ait à voir avec l'optimistic locking, qui resort des accès concurrents. On parle ici d'un client unique...
Marsh Posté le 25-08-2006 à 17:31:42
sircam a écrit : |
Oui en effet, nous on s'en sert aussi pour vérifier qu'entre la lecture des données et la modification effective (via une ihm), rien n'a changé, on évite ainsi de se prendre des exceptions oracle à la tronche, en anticipant...on dit "Oups ben désolé gars, faut recommencer là...ça a changé entre temps...".
On compare l'OL de l'objet chargé lors de la lecture avec celui en base (incrémenté auto à chaque modif), si c'est pas le même => dtc
Marsh Posté le 31-08-2006 à 17:42:09
Bon
Et bien, j'ai la solution. Soyons modeste : je ne l'ai pas trouvée moi-même. Elle vient de BEA.
J'attends une drapalisation massive avant de la poster, car je doute que ce topic ne suscite le moindre intérêt. Un flop de plus, comme à chaque fois que je pose une colle. Ce forum est rempli de bons à rien, à commencer par moi. C'est honteux.
Marsh Posté le 21-08-2006 à 18:18:04
Salut les javateux,
Je me permets de soumettre à votre sagacité le cas suivant.
L'application sur laquelle je bosse (Weblogic 8.1 SP5, Oracle 9i) plante sur un EJB select avec une SQLException renvoyant une erreur Oracle ORA-02291 : "constraint violation - parent key not found".
Le processus se déroule comme suit (de manière très résumée):
Notons que la contrainte déclenchée varie d'exécution en exécution (parfois, il s'agit de la contrainte PWH -> S, parfois BP -> SU). Parfois même, le processus complet se déroule sans encombre.
Je suspecte que c'est 3 fois rien, mais je suis un peu coincé. Problème config DB ou problème config Weblogic ?
J'ai déjà vérifié différentes pistes, sans succès : ordre d'accès aux entités, EJB transaction attribute, ajout de logging pas à pas pour déceler une anomalie crasse. Le coup de la mauvaise isolation de la transaction me semblait bon mais alors pq ça planterait à différents endroits, voire parfois pas du tout ?
Un petit stacktrace:
<@#2006-08-21 11:37:24 ERROR in foo at foo.RegisterMgmt@130b5bd[execute(),143][,]:
EJB Exception:; nested exception is: javax.ejb.EJBException: nested exception is: java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
javax.ejb.TransactionRolledbackLocalException: EJB Exception:; nested exception is: javax.ejb.EJBException: nested exception is: java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
javax.ejb.EJBException: nested exception is: java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
at weblogic.ejb20.internal.EJBRuntimeUtils.throwInternalException(EJBRuntimeUtils.java:178)
at weblogic.ejb20.manager.BaseEntityManager.executeInsertStmt(BaseEntityManager.java:629)
at weblogic.ejb20.manager.BaseEntityManager.executeDBOperations(BaseEntityManager.java:475)
at weblogic.ejb20.internal.TxManager$TxListener.executeDBOperations(TxManager.java:585)
at weblogic.ejb20.internal.TxManager$TxListener.executeDBOperationsDriver(TxManager.java:560)
at weblogic.ejb20.internal.TxManager$TxListener.flushModifiedKeys(TxManager.java:804)
at weblogic.ejb20.internal.TxManager.flushModifiedBeans(TxManager.java:319)
at weblogic.ejb20.manager.BaseEntityManager.flushModifiedBeans(BaseEntityManager.java:2600)
at weblogic.ejb20.cmp.rdbms.RDBMSPersistenceManager.flushModifiedBeans(RDBMSPersistenceManager.java:3818)
at fo.BooBean_ginnrm__WebLogic_CMP_RDBMS.ejbFindByBoo(BooUserBean_ginnrm__WebLogic_CMP_RDBMS.java:676)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at weblogic.ejb20.cmp.rdbms.RDBMSPersistenceManager.scalarFinder(RDBMSPersistenceManager.java:315)
at weblogic.ejb20.manager.BaseEntityManager.scalarFinder(BaseEntityManager.java:1794)
at weblogic.ejb20.manager.BaseEntityManager.localScalarFinder(BaseEntityManager.java:1743)
at weblogic.ejb20.internal.EntityEJBLocalHome.finder(EntityEJBLocalHome.java:543)
(...)
javax.ejb.EJBException: nested exception is: java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
at weblogic.ejb20.cmp.rdbms.RDBMSPersistenceManager.flushModifiedBeans(RDBMSPersistenceManager.java:3826)
at foo.BooBean_ginnrm__WebLogic_CMP_RDBMS.ejbFindByBoo(BooBean_ginnrm__WebLogic_CMP_RDBMS.java:676)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at weblogic.ejb20.cmp.rdbms.RDBMSPersistenceManager.scalarFinder(RDBMSPersistenceManager.java:315)
at weblogic.ejb20.manager.BaseEntityManager.scalarFinder(BaseEntityManager.java:1794)
at weblogic.ejb20.manager.BaseEntityManager.localScalarFinder(BaseEntityManager.java:1743)
at weblogic.ejb20.internal.EntityEJBLocalHome.finder(EntityEJBLocalHome.java:543)
at foo.BooBean_ginnrm_LocalHomeImpl.findByBoo(BooBean_ginnrm_LocalHomeImpl.java:167)
(...)
javax.ejb.TransactionRolledbackLocalException: EJB Exception:; nested exception is: javax.ejb.EJBException: nested exception is: java.sql.SQLException: ORA-02291: integrity constraint (FOO.SYS_C005155) violated - parent key not found
Désolé pour l'obfuscation malheureusement nécessaire.
BEA Weblogic 8.1 SP5
Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode)
Oracle 9.2.0.7
EJB 2.1
J'ai sans doute oublié l'uneou l'autre chose. Dites-moi ce que cela vous inspire.
Merci
---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}