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

Spring Java Discussion :

Hibernate lazy loading et édition par JSF, possible? bonne pratique?


Sujet :

Spring Java

  1. #1
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut Hibernate lazy loading et édition par JSF, possible? bonne pratique?
    Bonjour,

    J'ai commencé à faire des mappings de collection sur mes entités hibernate pour mon application JSF icefaces.
    J'utilise des DAO basées sur hibernateTemplate fourni par Spring.

    Si je prends un exemple tout simple :
    Une entité Group qui a plusieurs entités User.
    j'ai pour cela une propriété Set<User> dans le groupe, du tout simple.

    Une fois dans le managed bean, je ne peux plus utiliser la méthode group.getUsers(), ok c'est normal car la session est fermée. Je peux cependant utiliser le filter openSessionInView jusque là ok.

    Maintenant mon problème est que j'aurai besoin de stocker le Group en session pour pouvoir éditer ses utilisateurs et ses autres relations par le biais d'un formulaire étalé sur plusieurs pages. Le problème c'est que si le chargement du Group a été fait dans Step1.jsf, puis que l'accès a getUsers() se fait dans Step2.jsf ça explose car la session hibernate s'est terminée quand Step1 a été rendue...

    Donc en gros...
    -Est-ce mauvaise pratique que d'utiliser ses objets hibernate directement dans la vue JSF (liaison aux datatable et ça)?
    -Est-il incorrect de laisser un objet hibernate *survivre* entre les requêtes?

    -A-t-on pas intérêt à ne pas mapper les collections mais à tout gérer au niveau service avec des méthodes tels que :

    List<Users> GroupService.getUsersOfGroup( int idGroup, );
    GroupService.setUsersOfGroup( int idGroup, List<Users> ); ?

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Je crois qu'il faut bien comprendre qu'il y a 2 aspects ici :

    - persistance
    - IHM

    Mapper un collection dans un Entity (ou pojo si Hibernate "natif") n'a un sens que si d'un point de vue persistance, on en a besoin.
    En d'autres termes, il ne s'agit pas de mettre tous les SET représentant toutes les relations possibles entre des tables dans le mapping.

    D'un point de vue IHM, la question est centrée sur l'aspect de l'IHM.
    Si tu as besoin d'ajouter un utilisateur à un groupe, il faudra bien avoir 2 types d'objets.
    Savoir s'il faut utiliser le pojo ou l'Entity directement est un vieux débat.
    Personnellement, je pense que non (pour les EJB dumoins) parce que je ne veux pas supprimer le lazy loading pour des raisons de performances, je préfère passer par la couche DTO pour faire le lien entre mes objets persistants et mes objets d'IHM. C'est certes contraignant, mais d'un autre côté, on gagne en découplage...

    Avec les EJB, il y a maintenant SEAM qui permet de s'affranchir de la couche DTO et d'utiliser directement l'Entity (tout en gardant le lazy loading).

    Pour Hibernate "natif", hormis l'option fetch.EAGER qui chargera les relations, c'est plus aléatoire...
    Rien ne t'empêche cependant d'utiliser des fonctions DAO qui chargeront les liaisons (fetch join) dans la requête d'accès.
    Je n'aime pas trop parce que d'un point de vue IHM, je manipule un objet sans devoir me soucier du "comment" il a été chargé...

    Bref, je ne sais pas si ça t'avance...

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Savoir s'il faut utiliser le pojo ou l'Entity directement est un vieux débat.
    Personnellement, je pense que non (pour les EJB dumoins) parce que je ne veux pas supprimer le lazy loading pour des raisons de performances, je préfère passer par la couche DTO pour faire le lien entre mes objets persistants et mes objets d'IHM. C'est certes contraignant, mais d'un autre côté, on gagne en découplage...
    Je comprends, mais que cela m'embêterait de ne pas pouvoir utiliser mes objets hibernate dans ma couche IHM car cela m'obligerait à créer des objets qui sont dans bien des cas strictement identiques.
    C'est vrai que ça amène du découplage, mais j'aimerai éviter de multiplier les lignes de codes juste pour avoir un sentiment d'abtraction. Ici tout le monde est déjà à deux doigts de me dire que ce que je fais avec tous ces frameworks c'est de l'over-engineering par rapport à une bête servlet (mais je me défend férocement).

    Dans mon cas je pense qu'il est pertinent de ne pas me servir de mes objets hibernate au sens business objects full OO avec lazy loading, fonctionnalités métier etc... mais comme des data holders plus ou moins intelligents, assez pour gérer un peu de validation standard mais sans grand chose de plus.
    Si je dois gérer des fonctionnalités métier plus complexe, je les encapsulerai dans un objet plus puissant...

    C'est quand même commode de charger une liste de users mappées en utilisant un service.getUsers() et de binder tout ça à une datatable.
    Maintenant tant pis si je ne suis pas dans un super monde orienté objet et que je dois recourir à un service.getDroits( User ) au lieu d'un user.GetDroits().
    J'aurai au moins la possibilité de bien contrôler les accès aux données.

    Tu penses que ça se défend?

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _skip Voir le message
    Ici tout le monde est déjà à deux doigts de me dire que ce que je fais avec tous ces frameworks c'est de l'over-engineering par rapport à une bête servlet (mais je me défend férocement).
    Tu as bien raison
    Il y a beaucoup trop d'informaticiens allergiques aux changements, je me demande toujours pourquoi ils ont choisi ce métier
    Citation Envoyé par _skip Voir le message
    Dans mon cas je pense qu'il est pertinent de ne pas me servir de mes objets hibernate au sens business objects full OO avec lazy loading, fonctionnalités métier etc... mais comme des data holders plus ou moins intelligents, assez pour gérer un peu de validation standard mais sans grand chose de plus.
    Si je dois gérer des fonctionnalités métier plus complexe, je les encapsulerai dans un objet plus puissant...

    C'est quand même commode de charger une liste de users mappées en utilisant un service.getUsers() et de binder tout ça à une datatable.
    Maintenant tant pis si je ne suis pas dans un super monde orienté objet et que je dois recourir à un service.getDroits( User ) au lieu d'un user.GetDroits().
    J'aurai au moins la possibilité de bien contrôler les accès aux données.

    Tu penses que ça se défend?
    Ça se défend...
    Même si d'un point de vue maintenance/évolution tu induis des problèmes potentiels dans la couche IHM (donc JSF ici) avec des NullPointerException sur des objets non initialisés.

    Une alternative "élégante" dans un contexte Hibernate "natif" à base de pojo est de créer une session dans un filtre ou un contrôleur personnalisé, de l'utiliser dans le cycle request/response et de la libérer en sortie.
    De cette façon, tu ne risques plus le problème lié au lazy loading.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Pour seam, j'ai demandé il y a quelques jours sur le forum framework si c'était viable de l'employer sans jboss ou bien si c'était risqué, pas eu de réponse et il m'a semblé que c'était pas mal Spring, et surtout suffisamment répandu pour que je trouve de la documentation.


    Une alternative "élégante" dans un contexte Hibernate "natif" à base de pojo est de créer une session dans un filtre ou un contrôleur personnalisé, de l'utiliser dans le cycle request/response et de la libérer en sortie.
    De cette façon, tu ne risques plus le problème lié au lazy loading.
    En effet il est fourni un filtre de ce genre avec spring, il te permet de faire du lazy loading hors du contexte DAO (par exemple dans un managed bean JSF) mais ceci uniquement dans la "request" qui a chargé ton objet hibernate.
    Le postback suivant ça ne marchera plus.

    Les workarounds que j'ai trouvés dans les forums pour l'instant sont tous tellement moches que même moi j'arrive à voir que ce sont des hacks, parmi eux on retrouve des "session-per-session" qui explosent dès que ça passe les 15 utilisateurs.

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _skip Voir le message
    Pour seam, j'ai demandé il y a quelques jours sur le forum framework si c'était viable de l'employer sans jboss ou bien si c'était risqué, pas eu de réponse et il m'a semblé que c'était pas mal Spring, et surtout suffisamment répandu pour que je trouve de la documentation.
    Pas de problème, ça fonctionne également sur un serveur GlassFish
    Citation Envoyé par _skip Voir le message
    En effet il est fourni un filtre de ce genre avec spring, il te permet de faire du lazy loading hors du contexte DAO (par exemple dans un managed bean JSF) mais ceci uniquement dans la "request" qui a chargé ton objet hibernate.
    Le postback suivant ça ne marchera plus.

    Les workarounds que j'ai trouvés dans les forums pour l'instant sont tous tellement moches que même moi j'arrive à voir que ce sont des hacks, parmi eux on retrouve des "session-per-session" qui explosent dès que ça passe les 15 utilisateurs.
    Ce n'est pas vraiment un problème, tu peux faire un merge ou un refresh sur l'objet lors du request suivant...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    C'est dommage pour Seam que je n'ai pas su avant, ça me paraissait tellement orienté JBoss (au niveau IDE surtout) que j'ai pas osé de peur que ça me retombe dessus si je faisais tourner ça dans du tomcat.
    J'ai rien contre jboss sauf que nous avons pris l'habitude de tomcat et que j'ai l'impression que c'est plus lourd et démesuré pour ce que je veux en faire.

    Rattacher l'objet à une session?
    Mais je suppose que depuis l'UI je ne peux pas faire cela sans un appel à une méthode de ma DAO, ça fait qu'il faut que je me souvienne de faire ça pour les objet qui ont une portée au moins "request".

  8. #8
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Dans le cas du filtre qui prend en charge la session, ton UI à toujours la possibilité de récupérer les propriétés non initialisées, pas besoin de DAO pour ça
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    J'ai mis ça dans mon web.xml

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
            <filter-name>Hibernate Session In View Filter</filter-name>
               <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>Hibernate Session In View Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    Mais ça crame toujours si j'essaie de lazy loader une propriété d'un objet dans un managed bean JSF, est-ce que j'ai pu faire ça incorrectement?

  10. #10
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Je n'utilise pas Spring donc, je ne peux pas répondre...
    Ceci dit, si ça fait ce que je pense, ça devrait fonctionner, du moins pour le premier affichage.
    Pour les affichages consécutifs, c'est sûr que ça va planter si tu n'attaches pas le pojo à la session...
    C'est le premier appel qui plante ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Non, mais charger une entité pour laisser l'utilisateur la modifier lors de l'affichage de la page, puis ensuite appeler une propriété lazy lors d'un postback, ça oui ça plante.

    Mais à ce que j'ai pu lire, c'est assez peu recommandable .

  12. #12
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Ce que je disais avant...
    Pour les affichages consécutifs, c'est sûr que ça va planter si tu n'attaches pas le pojo à la session...
    tu pourrais le faire via refresh ou merge par exemple.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Oui, je pense que je vais m'habituer à faire des refresh, ça me permettra aussi peut être de gérer les cas ou les entités en édition ont été supprimés pendant qu'elles étaient détachées.

    Un poil moins chaud pour employer merge car si je comprend bien, il se peut qu'hibernate tente des modifications sur la DB pendant le processus, dans mon cas refresh ce sera parfait.

    En tout cas je te remercie.

  14. #14
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _skip Voir le message
    En tout cas je te remercie.
    Mais je t'en prie...

    (effectivement, merge fera la mise à jour en DB (si tu commit))

    PS : Attention à refresh(), les modifications seraient perdues ... ce n'est peut-être pas ce que tu veux
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Réponses: 8
    Dernier message: 09/01/2013, 05h28
  2. JSF et bonnes pratiques sur le scope des beans
    Par RiiiDD dans le forum JSF
    Réponses: 2
    Dernier message: 22/03/2011, 10h16
  3. hibernate, lazy loading et mémoire
    Par Graurk dans le forum Hibernate
    Réponses: 3
    Dernier message: 03/11/2010, 17h49
  4. Spring hibernate lazy loading
    Par mauroyb0 dans le forum Hibernate
    Réponses: 6
    Dernier message: 09/05/2007, 12h14
  5. [HIBERNATE 3]Lazy loading
    Par SEMPERE Benjamin dans le forum Hibernate
    Réponses: 11
    Dernier message: 08/02/2006, 22h40

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