[JAVA/JSP] gestion des doublons

gestion des doublons [JAVA/JSP] - Java - Programmation

Marsh Posté le 28-11-2008 à 11:09:50    

Bonjour,  
Je suis dans un moment clef d'un développement et j'aurai voulu avoir un conseil concernant la façon dont vous procèderiez de façon à optimiser mon traitement pour identifier les doublons en base pour un update sachant que la clef et la valeur sont uniques.
 
Les éléments sont les suivants :
- un tableau associatif construit à partir de valeurs postées en amont via un formulaire (clef/valeur)
- une base de données
 
Dois-je d'abord scanner mon tableau associatif pour identifier les doublons du tableau, faire directement un select et comparer les valeurs et les clefs en base ? Uniquement le champ valeurs et ensuite voir si l'id correspond bien à la clef du tableau ? Je ne sais pas si je suis clair...
 
Merci pour vos lumières :jap:  
 
hpl76


Message édité par hpl76 le 28-11-2008 à 13:17:44

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 28-11-2008 à 11:09:50   

Reply

Marsh Posté le 02-12-2008 à 10:37:59    

nobody ?


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 02-12-2008 à 13:35:35    

Non tu n'es pas clair !
 
Pourquoi utiliser un tableau si tu ne veux pas de doublons? Un Map (HashMap) serait plus approprié.
Tu veux identifier les doublons du tableau ou de la base?
 
- et si la valeur est unique, pourquoi utiliser une clef?

Reply

Marsh Posté le 02-12-2008 à 13:45:04    

Bonjour et merci de te soucier de mon "problème". Je suis assez noob donc excuse mes lacunes. J'utilise justement un hashmap pour stocker les valeurs postées depuis mon form vers ma servlet.  
 
En fait au final j'aimerai pouvoir dire :
Ok, s'il y a des doublons. Que voulez-vous faire ?
Annuler l'opération ou forcer la valeur...
 
J'arrive maintenant à afficher dans ma servlet ceci :
id 50 -> 608768
id 69 -> polo_po
id 51-> pastaga
 
Je me demandais si je devais déjà scanné mon tableau asso des fois qu'il y aurait un 4è enregistrement avec l'id 80 -> polo_po puis ensuite faire un autre scan dans la base. Comparer d'abord les valeurs puis regarder si l'id est le même car je peux très bien posté des valeurs sans les modifier...je sais pas si c'est plus clair.
 
Au final c'est repéré les doublons en base et dans le hashmap car il se peut que l'utilisateur saisisse id50 -> "abc" id51 -> "abc" et dans ce cas j'ai également un doublon. C'est une mise à jour de champ pour chaque clef (unique pour le coup) postée via un hidden (le principe du foreach PHP avec qui je n'ai pas de souci)
 
Merci à toi.
 
hpl76

Message cité 1 fois
Message édité par hpl76 le 02-12-2008 à 13:46:11

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 02-12-2008 à 21:25:50    

hpl76 a écrit :

Bonjour et merci de te soucier de mon "problème". Je suis assez noob donc excuse mes lacunes. J'utilise justement un hashmap pour stocker les valeurs postées depuis mon form vers ma servlet.  
 
En fait au final j'aimerai pouvoir dire :
Ok, s'il y a des doublons. Que voulez-vous faire ?
Annuler l'opération ou forcer la valeur...
 
J'arrive maintenant à afficher dans ma servlet ceci :
id 50 -> 608768
id 69 -> polo_po
id 51-> pastaga
 
Je me demandais si je devais déjà scanné mon tableau asso des fois qu'il y aurait un 4è enregistrement avec l'id 80 -> polo_po puis ensuite faire un autre scan dans la base. Comparer d'abord les valeurs puis regarder si l'id est le même car je peux très bien posté des valeurs sans les modifier...je sais pas si c'est plus clair.
 
Au final c'est repéré les doublons en base et dans le hashmap car il se peut que l'utilisateur saisisse id50 -> "abc" id51 -> "abc" et dans ce cas j'ai également un doublon. C'est une mise à jour de champ pour chaque clef (unique pour le coup) postée via un hidden (le principe du foreach PHP avec qui je n'ai pas de souci)
 
Merci à toi.
 
hpl76


Honnêtement ce n'est pas encore très clair. D'un point de vue général que penses-tu des cas suivants ?
 
Cas 1 (doublons sur la clé base-formulaire) :
Si l'entrée "id1" => "coucou" est présente en base et que dans ton formulaire l'entrée "id1" => "autre" est saisie.
 
Cas 2 (doublons sur la valeur base-formulaire) :
Si l'entrée "id1" => "coucou" est présente en base et que dans ton form l'entrée "id2" => "coucou" est saisie.
 
Cas 3 (doublons sur la clé et la valeur base-formulaire) :
Si l'entrée "id1" => "coucou" est présente en base et que dans ton form l'entrée "id1" => "coucou" est saisie.
 
Cas 4 (doublons clé formulaire uniquement) :
Si les entrées "id1" => "coucou" et "id1" => "autre" sont saisies dans ton form.
 
Cas 5 (doublons valeur formulaire uniquement) :
Si les entrées "id1" => "coucou" et "id2" => "coucou" sont saisies dans ton form.
 
Cas 6 (doublons clé/valeur formulaire uniquement) :
Si les entrées "id1" => "coucou" et "id1" => "coucou" sont saisies dans ton form.
 
Pour chaque cas, est-ce que c'est possible (est-ce que c'est censé arriver dans un fonctionnement normal) ? et comment souhaites-tu gérer la situation (que veux-tu obtenir au final comme résultat) ?


---------------
By bob.
Reply

Marsh Posté le 03-12-2008 à 10:35:07    

C'est ce que j'appelle un rapport :)
Merci à toi pour ton investissement, tu as quasiment tout compris.
 
Donc la finalité c'est de repérer s'il y a doublon ou non et de dire :
1 - "Je force (uniquement) les valeurs postées" (commit)
2 - "Je ne valide aucune valeur" (rollback)
 
Ce qu'on affiche dans le formulaire est forcément issu de la base et l'id est un champ caché (je le poste dans le form pour créer la corrélation et retrouver mes petits, un update de lignes)
 
cas 1 : mise à jour de la valeur pour l'id indiqué
cas 2 : alerte doublon !
cas 3 : valeur ne change pas si elle n'a pas lieu de l'être, update de la même valeur en quelque sorte
cas 4 : impossible, la clef est unique !
cas 5 : possible, dans ce cas, alerte doublon !
cas 6 : impossible, la clef est unique !
 
C'est un peu comme ci tu avais un back office pour mettre à jour le prix d'une liste d'articles issus de ta base. Chaque article a son propre id. Tu fais une mise à jour globale des prix de tous tes articles à l'écran mais tu repères si tu as saisi 2 fois le même prix ou, si tes prix saisis sont tous différents, vérifier qu'ils n'existent pas déjà en base. J'espère que c'est plus clair.
 
hpl76


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 03-12-2008 à 18:17:43    

hpl76 a écrit :

1 - "Je force (uniquement) les valeurs postées" (commit)


Dans ce cas, ça implique que tu supprime le couple id-valeur présent en base (ou que tu ignore le précédent détecté dans le formulaire) et que tu insère le nouveau couple clé-valeur correspondant, c'est bien ça ?
Sinon est-ce que les couples id-valeur en base de données représentent une volumétrie importante (par ex > 50 000 entrées) ?


---------------
By bob.
Reply

Marsh Posté le 03-12-2008 à 20:40:02    

Re,
 
Pas exactement, l'id, lui ne change pas et est unique. Ce qui vient du formulaire provient de la même table c'est comme si tu avais :
 
id nom     prix
1  banane  3
2  poires    4
3  figues    2
 
et que voulais éditer le champ prix (banane reste banane, poires : poires, figues : figues) mais si tu as 2 fois le même prix, ca te dit (hop hop hop t'es sur que prix banane = prix poires ?)
Ca prévient et ensuite l'utilisateur avise. On ne peut pas saisir d'id (champ caché posté)
 
Tu me suis mieux ?
 
Il n'y a pas 50 000 entrées lol heureusement pour moi ^^
 
hpl76


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 04-12-2008 à 13:50:36    

Ok, ça commence à être plus clair maintenant ...
Bon alors la solution à ton pb devrait être à peu près ça :
Tu as deux cas de figure :
A - L'utilisateur valide la première fois  
 => on ne sais pas s'il veut forcer, donc on fait une vérification de forçage avant de valider les données
B - L'utilisateur valide après avoir dit qu'il voulait forcer
 => on écrit tout sans rien vérifier
 
En ce qui me concerne, la meilleure technique, est de tout charger ta valeurs dans des objets java (Map pour les paires clé-valeurs et Set pour les valeurs).
Puis vérification pour chaque entrée saisie :
 - Si tu es dans le cas A, vérifie si la valeur a été modifiée (en regardant dans la map l'id associé) puis si elle a été modifiée, regarde si la valeur est présente (en regardant dans le Set). Si la valeur est présente arrête ton traitement et réaffiche la page en demandant à l'utilisateur s'il veut forcer. Si aucune valeur n'est présente, ajoute ou modifie dans ta Map et ton Set l'entrée du formulaire en cours (pour vérifier les entrées suivantes).
 - Si tu es dans le cas B, pas de traitement spécifique.
Puis insertion des données :
 - Si tu es dans le cas A et qu'il n'y avait aucun doublons, effectue tes insert/update sans soucis.
 - Si tu es dans le cas B effectue tes insert/update sans soucis.
 
J'espère que c'est assez clair, demande si tu veux plus de précision ...
Éventuellement poste le code que tu as fait qui correspond à ce traitement pour pouvoir mieux comprendre...


---------------
By bob.
Reply

Marsh Posté le 04-12-2008 à 14:15:28    

Merci Bob donc voilà ce que j'ai commencé à faire :
 
   

Code :
  1. //récup des données postées
  2.     String[] ids = request.getParameterValues("id" );
  3.     String[] vals = request.getParameterValues("valeur" );
  4.     //création de la corrélation, chaque id a forcément sa val
  5.     Map m = new HashMap();
  6.       for(int i=0;i<ids.length;i++){
  7.              m.put(ids[i],vals[i]);
  8.       }


 
C'est maintenant que ca se complique, je m'emmêle les pinceaux dans mon ou plutôt mes vecteurs et l'hashmap.  
 
J'ai essayé ceci :

Code :
  1. //on se connecte
  2.     ConnectionDB db=new ConnectionDB();
  3.     db.connect();
  4.     for (Iterator it = m.keySet().iterator() ; it.hasNext() ; ){
  5.     Object key = it.next();
  6.     Vector v=db.requete_query("SELECT * FROM ma_table WHERE ID='"+key.toString()+"' AND VAL ='"+m.get(key).toString()+"'" );
  7.    if (v.size()>1){out.print("doublon" );}
  8.     for(int j=0;j<v.size();j++){
  9.     String id=""+((HashMap)v.get(j)).get("ID" );
  10.     String val=""+((HashMap)v.get(j)).get("VAL" );
  11.     out.print(""+id+" -> "+"val"<BR />" );
  12.     out.print("size = "+v.size());
  13.     }
  14.     }


 
J'ai fait tellement de tests que je ne suis pas sur que ce soit le meilleur code que j'ai pondu :sarcastic:  
Je vois le problème du code ci-dessus c'est que je n'aurai jamais > 1 mais toujours = 1...Bref, mon idée c'est de parcourir l'hashmap, de faire un select (j'ai une classe de co), d'envoyer les valeurs dans mon vecteur pour récupérer le nom des champs et valeurs des champs en base et ensuite de dire "halte !" (ou pas) et ok ou bien un commit final mais ca m'échappe entre les doigts...
 
En tout cas merci de ton aide  ;)  
 
hpl76


Message édité par hpl76 le 04-12-2008 à 15:26:42

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 04-12-2008 à 14:15:28   

Reply

Marsh Posté le 04-12-2008 à 16:23:11    

Ben t'as deux solutions :
 - soit tu fais une requête select sql pour chaque entrée envoyée en paramètre du formulaire (ce que tu fais dans ton exemple)
 - soit tu fais une seule requête select sql au début de ton traitement pour alimenter une Map et un Set temporaire (ce que je te proposais)
La première est pas pénalisante si tu as très peu d'entrées saisies au formulaire, mais c'est "long" de faire autant de requete que d'entrées saisies si tu en as beaucoup.
La deuxième est pénalisante si tu as une forte volumétrie (d'où la question que je t'avais posée) mais est plus efficace si tu as une volumétrie gérable en base et le temps de traitement ne sera pas proportionnel au nombre de champs du formulaire (ce qui est a peu près le cas avec la première solution).
 
PS: évite "select *", pour plus de rigueur on conseille de nommer les champs que tu souhaite sélectionner (select monchamp1, monchamp2 from ...), ça permet d'éviter les soucis liés à l'évolution de structure table et ça permet de moins se mélanger les pinceaux.
PS: si tu as le choix évite d'utiliser Vector, préfère List (ArrayList) a Vector. Vector est une ancienne classe de Java d'avant le Collection Framework qui a tout repensé les classes "conteneurs" du style (liste, map, ensembles, ...).


---------------
By bob.
Reply

Marsh Posté le 04-12-2008 à 16:29:08    

Re Bob !
 
Merci pour tes conseils.
 
Sinon comment ferais-tu pour analyser les doublons saisies avant même de construire le tableau asso. Ca pourrait peut être me convenir, d'identifier dans un premier temps les doublons associatifs, dans un second les doublons hashmap/base.
 
J'ai fait ça mais, sans me mettre d'erreur, ca ne fonctionne pas :(
 

Code :
  1. Map m = new HashMap();
  2.       for(int i=0;i<ids.length;i++){
  3.          for (Iterator it = m.keySet().iterator() ; it.hasNext() ; ){
  4.          Object key = it.next();
  5.          if (m.get(key).toString().equals(val[i])){
  6.          out.println("doublon" );   
  7.          }else{
  8.          m.put(ids[i],val[i]);
  9.       }
  10.      }
  11.     }


 
Qu'entends-tu par un set temporaire ?
 
hpl76


Message édité par hpl76 le 04-12-2008 à 16:29:29

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 04-12-2008 à 17:36:16    

En gros je vais essayer de te reformuler la première partie de ce que je t'avais proposé comme solution :
 

Code :
  1. Map assocMap = new HashMap();
  2. Set valueSet = new HashSet();
  3. ResultSet rs = statement.executeQuery("SELECT ID,VALUE FROM MATABLE" );
  4. while (rs.next()) {
  5.   final String monId = rs.getString(0);
  6.   final String maVal = rs.getString(1);
  7.   assocMap.put(monId, maVal);
  8.   valueSet.add(maVal);
  9. }

ça c'est l'inititalisation où tu récupère toutes tes valeurs en base, valueSet est le set temporaire qui te permet de savoir si tu as des doublons,
La map te permet de tester si la valeur de ton entrée existe déjà (assocMap.get(id) != null) et si elle a été modifiée (!assocMap.get(id).equals(val))
A chaque entrée de ton form tu as juste à tester si valueSet.contains(val) et ça te dira s'il ya un doublon.
 
PS: c'est un exemple vite-fait en utilisant un statement jdbc (java.sql.Statement) déjà créé au préalable


---------------
By bob.
Reply

Marsh Posté le 09-12-2008 à 16:06:43    

Me revoilà, ca sent bon le "RÉSOLU" mais pas encore :)
 
Merci, ta façon de sortir dans une hashmap tous les données en base permet plus de souplesse.
 
Voici ce que j'ai fait :
création de l'hashmap bddmap (toutes les valeurs de la base)
création d'une hashmap postmap (toutes les valeurs postées)
 
Mon idée c'était de parcourir entièrement la postmap et de comparer avec toutes les valeurs de la bddmap mais je n'arrive pas à voir comment atteindre la colonne val de la bddmap :sweat:  
 
hpl76  :bounce:


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 14-01-2009 à 16:42:41    

J'ai bien progressé sur mon souci initial. Je bloque juste sur une requête mais surtout son exploitation pour pouvoir dire ensuite des Parisiens (champ ville) j'en ai 45, des gens de Toulouse (j'en ai 12)...Je ne suis pas sur de ma requête :
Vector v = db.requete_query("SELECT VILLE, Count(VILLE) AS NB_PAR_VILLE FROM CLIENTS GROUP BY VILLE" );
 
Comment ensuite afficher Paris -> 45, Toulouse -> 12...?
 
Merci par avance de votre aide.  
 
hpl76, vous souhaitant une très bonne année 2009 ;)


Message édité par hpl76 le 14-01-2009 à 16:44:12

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 20-01-2009 à 11:48:44    

Bonjour, personne ? Help me plz !


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 22-01-2009 à 17:26:35    

hpl76 a écrit :

Bonjour, personne ? Help me plz !


ConnectionDB, est-ce que c'est une classe maison ?
ConnectionDB.requete_query(String) <= apperemment ça te renvoie un Vector, mais un vector de quoi ???
J'ai l'impression que ton 'GROUP BY VILLE' n'est d'aucune utilité dans ce cas.
 


---------------
By bob.
Reply

Marsh Posté le 29-01-2009 à 15:22:02    

Là, Hpl76, il va falloir que tu bosses... le forum n'est sans doutes pas le bon endroit pour trouver des ressources pour écrire ton programme à ta place...

Reply

Marsh Posté le 30-01-2009 à 11:31:26    

Salut, c'est que tu n'as pas regardé mes posts, car figure toi que je planche sur la question. Tu verras par ci par là des morceaux de code que j'ai pu pondre. Désolé de ne pas avoir tes/vos compétences en la matière. Tu te méprends sur mes intentions. Peu importe je vais persévérer avec ou sans vous...Merci à toi superbob56 ;)


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 20-02-2009 à 14:45:12    

Bonjour, je reviens vers vous pour un tout petit souci. J'ai géré le tout en 3 étapes (une page.jsp, une servlet de comparaison, une servlet d'update)
 
Mon souci est que ma servlet d'update ne récupère pas toutes les valeurs postées de la servlet de comparaison. Elle ne récupère que la première ligne alors que j'ai repris le même principe qu'entre ma page.jsp et la servlet de comparaison pour le passage de valeurs.  
Je récupère les infos de cette façon :
String[] ids = request.getParameterValues("ID" );
avec un for derrière pour construire ma hashmap.


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 21-02-2009 à 12:59:50    

... euh ... tu ne crois pas que c'est un peu 'trop' de passer par une page jsp + 2 servlet ? ça me semble un peu 'lourd' comme archi pour un problème qui au fond n'est pas d'une complexité extrême, non ?
Sinon, si ça peut t'aider regarde du côté de request.getAttribute() pour avoir d'autres moyens de passer des paramètres entre servlets parce que request.getParameter() est vite limité (read-only et string uniquement) ...


---------------
By bob.
Reply

Marsh Posté le 23-02-2009 à 09:49:51    

Salut superbob56 et merci de ton aide. Je sais que l'exemple en soit n'est pas une complexité extrême mais j'ai préféré découper pour mieux gérer (c'est notamment dû à mon niveau de java). Je pense que je pourrais me passer de la dernière servlet mais je n'ai pas su faire autrement. Ma page .jsp est déjà blindé de conditions donc je ne pense pas que je vais y toucher. Ma 1ère servlet (2ème étape teste la décision utilisateur). Si on peut poster une variable de servlet à elle-même dans ce cas, pas de souci je veux bien squizzer la dernière, mais je ne sais pas si c'est possible...Je vais regarder en attendant ton getAttribute ;)


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 23-02-2009 à 16:41:07    

Apparemment on ne peut pas construire de tableaux avec cette méthode, ca ne m'arrange pas car j'arrivais à faire String[] mesids = request.getParameterValues("id" ); mais il ne me garde que la première ligne :'(


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 24-02-2009 à 12:09:55    

Je pense que tu te mélanges les pinceaux quelquepart.
En regardant la javadoc de getParameterValues tu peux lire : "If the parameter has a single value, the array has a length of 1."
J'ai l'impression que cette méthode ne fais pas ce que tu attends ...
Essaye de poser tranquillement ton problème, étudie bien la javadoc, fais des petits test pour vérifier que les méthodes et objet que tu utilise font bien ce que tu attends parce que sinon, tu risque de faire vraiment n'importe quoi ...
 


---------------
By bob.
Reply

Marsh Posté le 25-02-2009 à 11:43:30    

Bonjour, non j'ai déjà utilisé le getParameterValues pour passer mes id de ma page jsp à ma servlet 1 et c'était nickel, mais le passage de la servlet 1 à la servlet 2 avec la même façon de procéder ne fonctionne pas :\


---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 25-02-2009 à 14:19:59    

CA Y EST, ENFIN RÉSOLU !!!  
Je suis tellement obsédé par JAVA que j'en oublie la base, le b a ba.  
MERCI TOUT DE MÊME POUR TON AIDE SUPERBOB56 ;)


Message édité par hpl76 le 25-02-2009 à 14:23:18

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le 25-02-2009 à 16:36:16    

heureux que t'en sois sorti, mais ce qui serait pas mal pour la communauté c'est que nous dise ce qui n'allait pas et comment tu l'as corrigé (vu le temps passé sur le pb, ça serait sympa ;)...)


---------------
By bob.
Reply

Marsh Posté le 25-02-2009 à 17:01:58    

J'vais vraiment passer pour un con lol. En faisant un copier coller, mon form se trouvait dans la boucle d'où la mise à jour d'un seul champ, pour le reste je passe tout de ma page jsp vers une servlet 1 une qui se charge de contrôler les doublons et l'update se fait par la servlet 2. N'hésitez pas à me contacter par mp, je ne mords pas même pour ceux qui pensent que je viens là pour me faire engraisser et me faire développer mes applis. String[] mesids = request.getParameterValues("id" ); marche très bien ;)


Message édité par hpl76 le 25-02-2009 à 17:03:44

---------------
T'as pas de couilles au cul et quand tu en as c'est pas les tiennes :)
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed