Bonjour. Je viens tout juste découvrir le pattern DAO que je me pose quelque question. Par exemple sur OCR Herby propose
Bonjour. Je viens tout juste découvrir le pattern DAO que je me pose quelque question. Par exemple sur OCR Herby propose
L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
Nouveau sur le forum ? Consultez Les Règles du Club.
Oui , un oubli.
Pour la méthode find , il se peut qu'on veuille faire la recherche en fonction d'un autre critère que l'id. Dans ce cas faudrait-il utiliser 4 interfaces(pour chaque xxxDAO)?
Le pattern DAO définit juste un moyen d'accèder à une source de données, de manière indépendant de cette source (que ça soit une base de données JDBC, un serveur de fichiers, un système de persistence d'objet, etc).
Il n'y a qu'une seule interface ici, qui définit le CRUD (Create/Read/Update/Delete) : les 4 actions qu'on peut avoir à faire. On pourrait découper en plusieurs interfaces, si on voulait séparer les notions "Lecture Seule" et "Lecture/Ecriture". La méthode find(id) donnée dans l'exemple, n'est qu'une version simplifiée de l'action Read. En plus rien n'empêche d'avoir plusieurs méthodes pour chaque action. Par exemple, on peut avoir une méthode find(id) pour trouver l'objet suivant son id, et une méthode find(IFilter) avec IFlter une interface fonctionnelle, pour trouver des enregistrements selon une combinaison de critères quelconques. tu peux même avoir une méthode getAll() (qui retourne un itérateur paginé, pas la liste de tous les enregistrement...).
L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
Nouveau sur le forum ? Consultez Les Règles du Club.
Merci beaucoup pour votre réponse. J'ai donc essayé de faire une méthode trouver un peu générique
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 public OperateurPhysique[] trouver(String filtre, Object... objs) { ResultSet res; OperateurPhysique[] ops = null; String sql = "SELECT * FROM matable WHERE "; StringTokenizer tokens = new StringTokenizer(filtre, ";"); int t = objs.length; for(int i = 0 ; i < t ; i++) { if(i == 0) sql += tokens.nextToken() + " = " + objs[i]; else sql += "AND " + tokens.nextToken() + " = " + objs[i]; } //reste du code }
Ainsi
exécutera la requête
Code : Sélectionner tout - Visualiser dans une fenêtre à part trouver("nom;prenom" , "Lupin" , "Arsene")
Bien sur je compte utiliser des requêtes préparées plus tard.
Code : Sélectionner tout - Visualiser dans une fenêtre à part SELECT * FROM matable WHERE nom = 'Lupin' AND prenom = 'Arsène'
Qu'en pensez vous?
Je pense qu'il vaudrait mieux utiliser les PreparedStatement au plus tôt. Par contre, attention à la problématique d'être très lié à une base de données relationnelle SQL, dans le cadre général d'un DAO.
Dans la pratique, comme il est plus complexe de faire un DAO complètement générique du point de vue du système de persistance, on peut faire, comme tu as fait, un filtre SQL si on a un SGBD SQL, surtout qu'il y a peu de risque que cela change un jour dans l'application.
Mais, ça ne coûte pas grand chose et ce n'est pas spécialement très complexe de faire un filtre un peu plus abstrait, donc au lieu d'une chaîne de faire des interfaces pour manipuler un arbre de conditions, et faire une unique implémentation concrète qui transforme cet arbre en SQL. Ça prend beaucoup plus de temps quand même que pour une simple String, mais par rapport à un filtre pour PreparedStatement, on a des éléments similaires.
Ainsi, migrer d'une base vers autre chose, n'impliquera que l'implémentation du DAO concrète, pas les classes qui l'invoquent. De même pour le parcourt du résultat, qui devrait se faire en externe (pour rendre totalement transparent le parcourt de résultat réduit, complet, partiel, paginé, etc..., une sorte ResultSet DAO). C'est en tout cas un exercice intéressant à faire dans le cadre du travail sur les DAO.
L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
Nouveau sur le forum ? Consultez Les Règles du Club.
Merci. Mais disons que je ne suis pas vraiment un expert en ce qui concerne les interfaces. Pour la deuxième suggestion, ma méthode devrait prendre en paramètre un objet implémentant l'interface (disons ResultSetDAO) , c'est ça? Je ne sais pas trop comment faire pour rendre le filtre plus abstrait.
Pour faire une Interface, il suffit de lister ce dont on va avoir besoin. Si je dois faire une interface qui doit récupérer une propriété, je vais y mettre une méthode String getString(String name) par exemple, plus une méthode qui permet de récupérer une propriété int, une pour une propriété boolean, etc. Dans le DAO de l'application sur laquelle je bossais il n'y a pas longtemps, on avait une méthode getProperty(String name) qui retournait un IPropertyValue<T>, avec en implémentation concrète un StringValue, un IDValue, un CollectionValue, pour les éléments liés (lien 1-n), etc.
ResultSetDAO, ce serait plutôt le type de retour. Une interface avec une méthode qui permet d'avancer dans le résultat (une méthode hasNext() et une méthode next() par exemple), et qui permet de récupérer toutes les propriétés (donc la liste de noms de propriétés, et pour chaque propriété, son type (java) et sa value), ou alors c'est next qui retourne un enregistrement (une instance d'une classe qui a ces méthodes). Ensuite, on peut toujours l'enrichir, pour avoir une méthode qui donne le nombre d'enregistrements par exemple.
Le filtre, c'est juste un arbre de noeud. Dans l'optique, encore une fois, d'être très générique et, donc, indépendant de la façon de stocker le données. On pourrait également décider de mettre au point un petit langage d'expressions, dont l'arbre serait l'AST (Abstract Syntax Tree). Mais si tu ne te sens pas capable de le faire, tu peux te contenter pour commencer de faire un DAO qui ne traite que du SQL/Statement ou SQL/PreparedStatement.
Sinon dans l'optique de modéliser l'arbre par les classes (sans définir un langage et donc faire un parser) Chaque noeud correspond à un critère "unitaire". L'arbre/Expression est la combinaison des critères. Il y a des critères sans niveau (un arbre à un seul noeud, comme une égalité par exemple), et des critères multiples, à plusieurs niveaux (par exemple, pour faire un AND ou un OR).
Par exemple, voici un arbre (chaque ligne est un nœud) :
Qui sera traduit au final en SQL de prepared statement : par "a=? AND b = ? AND c like ? AND ( x<=? OR X>? )"ET a = 42 b = "abcd" c commence par "a" OU x <= 10 x > 100
Le critère le plus simple, c'est :
- un nom d'objet (de table en SQL)
- un nom de propriété (colonne de table en SQL)
- un opérateur de comparaison (=, >, commence par, etc.)
- une valeur à comparer
Ensuite, tu pourras avoir des critères à 2 valeurs (avec un opérateur entre ... et ...), à plusieurs valeurs (avec un opérateur "parmi"...),
Ce qu'il faut c'est être capable de produire du SQL, ou n'importe quelle autre syntaxe pour exprimer un filtre, en théorie. C'est là l'une des complexité, c'est-à-dire que tu peux tomber dans un travers qui fera que tu ne peux générer que du SQL au final. Cependant, c'est une approche qui simplifie le travail intellectuel, et tu pourras toujours sortir cette partie ensuite, pour traiter une autre façon de faire le filtre si besoin. L'avantage c'est que ça n'aura aucun impact sur la manière de construire l'arbre, donc sur le code métier. Par exemple si tu commences par faire une interface pour représenter un nœud qui a une méthode toSQL() qui génère un PreparedStatementBuilder (une classe qui permet de créer un preparedStatement prêt à être exécuté, avec ses paramètres injectés), ce n'est pas très compliqué à faire (c'est juste une classe, qui a un attribut StringBuilder, et une liste de valeurs (avec un moyen de sélectionner le bon injecteur, donc soit un type de données, soit directement l'invocation de l'injection, en utilisant un lambda)).
L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
Nouveau sur le forum ? Consultez Les Règles du Club.
Comme le disais joel.drigo, l'exemple que tu montres est un cas particulier (CRUD).
La méthode find est lié à la clé primaire de l'enregistrement dans la table et ne renvoit qu'une seule instance.
Il ne faut pas la confondre avec une méthode de recherche qui pourrait renvoyer une liste d'objet. Là, effectivement, tu auras à composer avec des arguments de filtre variable.
Généralement, on utilise une couche générique pour la partie CRUD et une couche spécialisée qui l'étend ou qui la contient pour la partie implémentation dans le cadre d'une application donnée. On est en plein dans le cadre du pattern facade, très utile surtout avec les EJB (vu qu'on peut être ammené à changer de conteneur entre l'application demandeuse et la couche EJB)
Pour la méthode de recherche, il y a plusieurs façon de procéder, ceci-dit, ton exemple avec un paramètre "quels champs" et un autre paramètre "valeur de comparaison" me paraît tout de suite limité, dans l'idée, j'aurais préféré un nombre dynamique de paramètres contenant le couple "champ=valeur" parce ça rendrait plus lisible, par exemple :
- "champ1=valeur"
- "champ1=valeur1|valeur2|valeur3"
Dans les 2 cas, il sera difficile de traiter des relations entre les conditions (and/or)...
N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager