IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Persistance des données Java Discussion :

Implémentation du pattern DAO


Sujet :

Persistance des données Java

  1. #1
    Membre à l'essai Avatar de VS7EVEN
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Points : 13
    Points
    13
    Par défaut Implémentation du pattern DAO
    Hello à tous ,

    Je suis actuellement occupé à développer une app Java avec le pattern DAO.

    Lorsque j'implemente la methode find(id), par exemple, j'aimerais savoir que dois je faire si je ne trouve pas dans la base de donnée le tuple avec l'id passé en paramètre.

    Est ce que je retourne l'objet avec des attributs incorrect, je peux retourner une exception... ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par VS7EVEN Voir le message
    Est ce que je retourne l'objet avec des attributs incorrect
    Autrement dit, mentir à l'appelant en lui faisant croire que l'objet existe. Je te laisse imaginer le nombre de bugs que tu va créer en aval

    Suivant comment tu veux géré ça de ton point de vue business:

    retourner une exception
    retourner null
    retourner un optional vide? (Je ne suis pas un grand fan de l'implémentation java des Optionals, mais parfois ça limite le nombre de checks en aval)

  3. #3
    Membre à l'essai Avatar de VS7EVEN
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Merci pour ta réponse

    Retourner null je ne suis pas fan (tout comme retourner un objet incorrect) parce que ça veut dire qu'il faut vérifier plus haut la référence.

    L'exception me plait bien mais de coup ça peut être vite chiant si elle doit remonter quelques appels de méthodes plus haut, à moins qu'on qu'il y ai un méthode pour éviter ce genre de problèmes.

    Les optionals je ne connais pas je vais aller voir ce que c'est

    Mais du coup le pattern DAO ne définit pas spécialement comment gérer ce type de cas ? C'est au développeur à choisir ?

    Je suis preneur pour également d'autres avis.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Citation Envoyé par VS7EVEN Voir le message
    Retourner null je ne suis pas fan (tout comme retourner un objet incorrect) parce que ça veut dire qu'il faut vérifier plus haut la référence.
    C'est assez courant pourtant. Et c'est toujours mieux que de renvoyer n'importe quoi. A défaut de soulever une exception, il te faudra retourner quelque chose. Faire un code du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Machin machin = dao.getMachin(id); 
    if ( machin!=null ) {
       //
    }
    else {
       //
    }
    n'est pas abérrant et plutôt usuel.

    Avec Optional, tu auras plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Optional<Machin> machin = dao.getMachin(id); 
    machin.ifPresent( ... );
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Machin machin = dao.getMachin(id); 
    if ( machin.isPresent() ) {
       //
    }
    else {
       //
    }

    Citation Envoyé par VS7EVEN Voir le message
    L'exception me plait bien mais de coup ça peut être vite chiant si elle doit remonter quelques appels de méthodes plus haut, à moins qu'on qu'il y ai un méthode pour éviter ce genre de problèmes.
    Bah, ça c'est courant aussi. Et puis l'exception dans un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Machin machin = dao.getMachin(id);
    ça permet de distinguer précisemment les cas (pas d'objet avec l'id demandé, pas de table, pas de base ou connexion perdue, etc.).
    Si c'est imposer le catch() qui t'ennuie, tu peux utiliser une RuntimeException, mais ça aura le défaut que l'utilisateur du DAO devra être rigoureux et s'intéresser aux exceptions, sinon, elles remonteront tout en haut du thread, et son programme risque de planter salement, au lieu d'avoir une gestion d'erreur au poil, du genre afficher un message quand l'utilisateur demande un objet inexistant, et se reconnecter automatiquement si la connexion est perdue, ou afficher un message d'avertissement (ou d'attente) si la connexion ne peut pas être rétablie, etc.


    Citation Envoyé par VS7EVEN Voir le message
    Mais du coup le pattern DAO ne définit pas spécialement comment gérer ce type de cas ? C'est au développeur à choisir ?
    Le pattern, c'est une question d'architecture, pas vraiment de traitement d'erreur. Après, niveau architecture, il y a différentes façosn de résoudre le cas. On peut opter par exemple par une solution par callback :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void processMachin(String id, Consumer<Machin> ifSucceed)
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void processMachin(String id, Consumer<Machin> ifSucceed, BiConsumer<String,Exception> inCaseOfError)
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Machin getMachin(String id, Consumer<Machin> ifSucceed, Consumer<String> ifUnknown, BiConsumer<String,Exception> inCaseOfError)
    L'appelant choisit d'appeler la méthode qu'il veut, en fournissant les handlers de callback qu'il veut gérer. Et ce n'est pas exclusif à l'implémentation classique pour celui qui veut utiliser l'appel classique avec try/catch et tout.
    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.

  5. #5
    Membre à l'essai Avatar de VS7EVEN
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Un tout grand merci pour vos explications

    Je crois qu'au final je vais utiliser les exceptions pour éviter de devoir tester la valeur de retour.

    L'idée du callback est aussi assez intéressante

    J'ai également une autre question concernant ce pattern lors de l'implémentation du find. Il se peut des fois que l'objet a retourner pointe sur d'autres objets (attributs de l'objet) qui eux même pointes sur d'autres. Du coup ça fait des requêtes SQL et la création d'objets en chaîne pour retourner juste l'objet, qui pourrait altéré les performances.

    Je sais pas si mes explications sont claires mais c'est assez chaud à décrire en fait e

    Du coup je me demandais comment faire pour pallier à ce problème ?

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    1. Il est tout à fait possible de procéder récursivement : l'implémentation de la méthode d'instanciation de l'objet peut intégrer des appels pour chaque objet lié.
    2. Cependant, cela poser de vrais problèmes de performances parce qu'en effet, comme tu le dis, un objet peut avoir des liens sur un objet qui a des liens sur un objet, qui a des liens sur un objet... etc, sur un nombre important de niveaux.
    3. Et il faut penser aux cycles : un objet A qui a un lien sur un objet B ... qui a un lien sur un objet Z qui a un lien sur l'objet A. Il faut donc éviter la boucle infinie.
    4. Tout d'abord on peut procéder par chargement lazy. Le chargement de l'objet lié est effectué par le DAO uniquement au moment où le getter est invoqué. Cela peut être également vrai pour certaines propriétés particulière (par exemple, un blob ou un fichier joint, un clob...)
    5. Ensuite, il peut être intéressant de mettre en place un système de cache, pour économiser les appels à la base de données.
      1. au plus simple conserver tous les objets chargés en mémoire, Mais ça peut poser des problèmes de mémoire.
      2. conserver un maximum d'objets, les plus utilisés, les derniers utilisés.
      3. cela peut poser également un problème en multi-utilisateur sur l'obsolescence de l'état d'un objet. Un objet dans le cache peut avoir été modifié dans la base. Le cache devrait être mis à jour dans ce cas.
        1. Selon les systèmes, on peut utiliser des systèmes de notification, qui permettent au cache d'être à jour, relativement. Ou utiliser un système de tag qui permet au cache de savoir s'il est à jour.
        2. On peut également faire du cache partiel selon le type de données. Certains objets peuvent ne jamais être modifiés (une liste de pays par exemple), ou rarement (et on considère ça comme négligeable), ou on peut ignorer fonctionnellement qu'ils puissent être modifiés et admettre que tant que l'utilisateur ne relance pas l'application, il aura les anciennes valeurs (on peut aussi fournir des moyens de rafraîchissement à la demande, ou faire des caches locaux à certaines fonctions).
        3. On peut gérer de façon différente les différents objets (par exemple, identifier des objets qui ne peuvent être modifié que par un seul utilisateur, comme des objets qui seraient dans un dossier Mes documents).
        4. On peut gérer les objets dans le cache différemment selon la fonction : en R, on peut admettre une obsolescence sur certains objets (on peut indiquer l'heure de validité de l'information, et mettre un bouton de rafraîchement que l'utilisateur cliquera s'il est intéresser par une donnée plus à jour), et U, on forcera un rafraichissement, et on posera un verrou pour éviter que l'objet ne change pendant la période d'édition.
        5. etc.
    6. Pour certains objets, on peut considérer que le chargement de l'objet lié doit être fait à la demande du programmeur et fournir une méthode de convénience orienté dans ce sens, comme charger certaines métadatas, ou un document joint...
    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.

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Il y a plusieurs stratégies possibles.

    La technique JPA / Hibernate: les objet retournés sont enrobés dans des proxy, les collections et objets liés sont chargés de manière déférée en lazy:
    • globalement ok coté performances
    • évite de surcharger la mémoire
    • pose problème avec les transactions
    • peux impliquer de nombreuses requetes là où un seule aurait été suffisante

    La technique je précharge tout
    • Peu viable pour les graphes d'objet
    • mémoire consommée
    • performance médiocre


    La technique des DTO sans liens (que les id des foreign key, a l'appelant de charger)
    • Léger à charger
    • beaucoup de boulot pour l'appelant
    • risque d'appelr 50 fois le même chargement d'objet si graphe d'exécution complexe
    • Pas très OO


    La technique du DTO / DAO spécialisé: en fonction du besoin, créer des méthode qui chargent des sous parties du graphe seulement
    • Consommation mémoire / réseau limitées au besoin
    • chargement unique des données
    • nécessite de savoir à l'avance ce dont on aura besoin
    • multiplication des DAO spécialisés

  8. #8
    Membre à l'essai Avatar de VS7EVEN
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2013
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Hello,

    Un tout grand merci pour vos réponses très utiles Je vais aller fouiller tout ça

    PS: désolé de répondre seulement maintenant mais je suis actuellement en voyage et je code de temps à autres quand j'ai du temps libre

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Implémenter pattern DAO
    Par merlin1977 dans le forum Général Java
    Réponses: 4
    Dernier message: 29/01/2014, 10h30
  2. [EJB3] implémenter EJB3 et DAO
    Par toomsounet dans le forum Java EE
    Réponses: 4
    Dernier message: 14/05/2007, 09h30
  3. Réponses: 5
    Dernier message: 10/05/2007, 16h03
  4. Implémentation du pattern Factory
    Par tut dans le forum C++
    Réponses: 6
    Dernier message: 02/08/2006, 13h43
  5. [Plugin][Hibernate] Patterns DAO avec hybernate
    Par BarbapapaDK dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 13/03/2006, 09h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo