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

Hibernate Java Discussion :

Persistance et organisation du code


Sujet :

Hibernate Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut Persistance et organisation du code
    J'ai pour habitude, lorsque je développe un projet, de bien séparer les couches de l'application et généralement, pour la persistance, je crée une classe qui servira d'interface entre le monde metier et le monde persistance.
    Cette classe regroupe les différentes actions faisables sur la base et permet ainsi en cas de changement de persistance de conserver intacte le code metier (simple redefinition des methodes de cette classe)

    Mais la avec hibernate, je n'arrive pas a mettre en place une tel solution : en effet je me retrouve bloqué car les fonctionnalitées interessantes d'hibernate nécessitent que les objets soit persistant. Les actions successives doivent donc avoir lieu au sein de la même session.

    Donc ma question est, pour les habitués d'Hibernate comment conserver vous un code metier non pollué (ie: j'aimerai éviter les appel a HibernateUtil dans tout les coin ou j'ai besoin de persister) tout en pouvant tiré parti des fonctionnalitées d'hibernate (lazy loading ...) ? Des explications, des exemples (petit diagrammes ...)
    La posix attitude ...

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    Voici un petit exemple illustrant mon problème :

    Ce code permet de recuperer un utilisateur dans la base de donnée et de le placer dans une Collection :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public User recupererUser(int idUser){
            User util = null;
            
            /*On regarde si l'utilisateur est toujours dans la liste des user connecté*/
            for(User us : users)
            {
                if(us.getId() == idUser)
                {
                    util = us;
                    break;
                }
            }
            
            //On va rechercher dans la base de données
            if (util == null)
            {
                   //util = gestionPersist.recupererUser(idUser);
                Session s = HibernateUtil.currentSession();
                Transaction tx = s.beginTransaction();
                
                 util = (User) s.get(User.class,idUser);
                
                tx.commit();
                HibernateUtil.closeSession();
                
                    if (util == null)
                    {
                            throw new IllegalArgumentException() ;
                    }
                    users.add(util); //On le remet dans la liste des user connécté
            }
            return util;        
        }
    la ligne en commentaire illustre l'utilisation de ma classe de gestion de persistance. Or a la fin de cette methode, je clos la session donc le lazy loading sur mon objet User (qui possède une collection ne peut plus marcher ...

    Exemple dans une autre méthode de la classe de gestion des users

    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
    21
    22
    public String ajouterFichier(int idUser, FileItem fichier){
     
            User us;
            try {
                us = recupererUser(idUser); //Exception a gerer
            }
            catch (IllegalArgumentException e){
                throw e;
            }
            StockageFichier stock = new StockageFichier(us.getNom()+us.getPrenom(),fichier);
            stock.stocker();
            Fichier fic = new Fichier(fichier.getName());
            Session s = HibernateUtil.currentSession();
            Transaction tx = s.beginTransaction();
            s.lock(us,LockMode.UPGRADE);//L'utilisateur est detaché de la persistance donc pb pr lazy loading il faut le réattacher manuellement
            s.refresh(us);
            us.addFicher(fic); //Une fois réattaché le lazy loading fonctionne (sinon exception)
            fic.creerLiens();
            tx.commit();
            HibernateUtil.closeSession();
            return fic.getLienPage();
        }
    Illustraton du problème avec le lazy loading : sans réattacher l'objet pas moyen d'ajouter des fichier a sa collection.
    On voit bien que le code n'est pas très élégant, que les methode de gestion d'hibernate n'ont pas a etre ici : vous me direz pourquoi ne pas faire cette action dans une methode de la persistance :
    1. J'y ai pensé, mais es-ce que une action comme user.addFichier() a t'elle bien sa place dans la persistance (perso je ne pense pas)
    2. Je vais être ennuyer à chaque fois que je vais vouloir acceder à mes éléments de la Collection de l'user (le lazy loading ne fonctionnera pas puisque l'objet est détaché ...
    Voyez vous une solution pour rendre tout cela moins fouilli structurellement parlant ? Moi je sèche ...

    Perso je pense que éliminer le lazy loading éviterai certains problèmes mais je perds alors une fonctionnalité clé d'Hibernate ce qui me dérange quand même pas mal.
    La posix attitude ...

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    En fait ce que je voudrais concretement c'est une explication sur l'integration d'hibernate dans une vrai application, parceque tout ce que l'on trouve sur le net c'est facile, hop de classe bidon un mapping et une classe de test ...

    Mais bon c'est pas ca qui va expliquer comment architecturer une vrai application, où gère t'on les sessions, où placé au mieux et sous quel forme les accès à la base (des classes spécifiques, dans les classes metier (mouais)) comment intégré tout ca dans un environnement web ...

    Voila j'ai a présent bien compris les notions d'hibernate comme l'état des objets, le loading ... mais je voudrais bien de l'aide pour savoir comment intégrer tout cela et tirer le meilleur parti d'hibernate.

    Donc si vous avez des diagrammes UML, des appli open source, des explications concrètes ou tout autre a me faire circuler où je pourrais voir tout cela je vous en serais grandement reconnaissant ...
    La posix attitude ...

  4. #4
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Si je devais répondre à ta question, je dirai qu'il y a plusieurs solutions. Encore une fois, je te renverrai vers la doc HTML Hibernate qui contient toutes les infos les concernant, je vais t'introduire ici même à la problématique :

    Il faut, dans un premier temps que tu définisses une stratégie de connexion à ta base de données. Tu as deux solutions majeures :
    1/ Une session longue. Tu gardes ta session ouverte durant tout le temps de manipulation des objets et ne la ferme qu'une fois tout terminé.
    2/ Des sessions courtes.Tu instancies une session à chaque opération en base de données. Cette stratégie implique dirons nous une plus grande complexité dans la gestion des objets, et notamment face au lazy loading; car, pour conserver un objet entre deux sessions, il faut utiliser le détachement des objets, mais le chargement tardif ne fonctionne pas sur les objets détachés ...

    En plus de cette stratégie, il existe aussi des stratégies d'accès concurrentiel :
    1/ Optimiste avec champ date ou version. Obligatoire pour l'utilisation des sessions courtes puisque les verrous basiques de DB ne durent que lors de sessions/transactions il me semble, à moins que tu ne gères toi-même tes verrous.
    2/ Pessimiste. Ici, tu poses un verrou à chaque utilisation d'un objet dans le cadre de transactions atomiques.

    Il faut enfin que tu redéfinisses la stratégie de chargement des objets. Pour cela, tu as :
    1/ Lazy loading. Chargement tardif des objets associés à ton objet manipulé. Connait des problèmes si tu utilises des sessions courtes ainsi que le problème du N+1 Select (1 requete pour acceder à l'objet et ses identifiants, N pour charger chaque objet de la liste d'objets associés).
    2/ Batch-size. On charge une partie des objets par lots, le reste étant réalisés en chargement tardif (moins couteux que le lazy loading).
    3/ Fetch group (ou nom similaire). Chargement d'une association complete.
    4/ Aucun. Tout se charge en une requete, mais si le graphe est trop complexe tu risques fortement de charger directement toute la base, et la tu te confrontes à des problèmes de performance.

    Une fois tout cela défini, tu peux réaliser ton programme en fonction de ces critères et mapper correctement tes objets avec la base.

    D'un point de vue "architecture", je considérerai l'API Hibernate comme un service et te permettant de gérer la persistance de tes objets. Autrement dit, dans chacune de tes classes métiers, tu ne toucheras jamais au code Hibernate, et lors de tes traitements, tu feras appel à ce service de persistance pour qu'il s'occupe lui même de tout le code Hibernate.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //exemple, pour sauvegarder, tu ne fais pas : 
    monobjet.save();
    //mais plutot
    manager.save(monobjet);
    // où manager est de type IManager (une interface) 
    //et instancié comme un HibernateManager (qui implémente l'interface IManager)
    La gestion des sessions se fera de deux manieres différentes :
    sessions courtes : ton manager peut traiter unitairement les sessions à l'interieur de chacune de ses fonctions.
    sessions longues : tu dois alors peut etre externaliser cette gestion via un objet Session que tu créeras. Puis lors de l'instanciation du manager, tu lui passe la session en paramètres, etc...

    Enfin voila, je pense que chaque strategie possède sa propre architecture et il n'existe pas une seule et unique solution, voici donc juste une proposition . (Perso, c'est aussi celle que j'utilise)

    Pour les choix strategiques, c'est à toi de regarder du coté des besoins de ton application, des traitements que tu réalises, etc. pour bien déterminer la mieux adaptée à ce que tu recherches.
    See you, space cowboy... and if you're satisfied, click on

  5. #5
    Membre actif
    Inscrit en
    Mai 2005
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 217
    Points : 220
    Points
    220
    Par défaut
    Perso, pour une webApp, j'ai opté pour le lazyloading et donc les sessions courtes ...

    Pour le reste, il faut veiller egalement à la struture de la base car meme si la normalisation est une bonne chose en terme de redondance et pour assurer un SI coherent, elle generer neanmoins une multiplication des requetes ... donc il faut trouver le bon compromis.

    Sinon comme l'a dit bizu, l'utilisation d'un manager (avec interface) est sans aucun doute, la solution architecturale la plus propre car elle est la moins intrusive dans le code metier (respect de la separation couche persistance <-> couche metier)

  6. #6
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Citation Envoyé par _beber85
    Perso, pour une webApp, j'ai opté pour le lazyloading et donc les sessions courtes ...
    La lazy loading est dangereux lorsque l'on opte pour les sessions courtes.

    Menfin, cela mis à part, la solution est tout de même viable mais comment gère tu justement cet accès aux objets chargés tardivement ? Tu crées une session à chaque traitement du style (enfin requete HTTP si l'on en croit le second document justement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    manager.startSession();
    manager.attach(monobjet);
    //traitements
    manager.detach(monobjet);
    manager.closeSession();
    ?
    See you, space cowboy... and if you're satisfied, click on

  7. #7
    Membre actif
    Inscrit en
    Mai 2005
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 217
    Points : 220
    Points
    220
    Par défaut
    ouais ms c plus du style

    manager.save(monObjet) <- l'ouverture session, l'attachement et la fermeture son géré dedant

  8. #8
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Ah donc c'est vraiment des sessions très courtes... et non synchronisé avec les requete HTTP.

    En terme de performance, tu dois donc rattacher ton objet et le detacher à chaque fois.... es tu sur que tu rentre bien dans un cadre de "bonne performance" ?!? Ca ne coute rien d'effectuer ces opérations à répétition ? Surtout quand il s'agit de manipuler une masse d'objets non ?
    See you, space cowboy... and if you're satisfied, click on

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    Tout d'abord merci bien Bizur et Beber

    Donc moi ce genre de code me conviendrait bien
    manager.startSession();
    manager.attach(monobjet);
    //traitements
    manager.detach(monobjet);
    manager.closeSession();
    mais toujours le même problème : la methode attach va ouvrir une session, sans la fermer (pour garder l'objet attaché) et la methode detach va fermer cette session. J'ai bon ??

    Or dans une appli comme la mienne (plein de threads : webapps) cela se gere comment ? Pour moi l'objet manager est clairement un singleton (c'est comme cela que je l'ai fait dans mon appli)
    donc si jamais quelqu'un intercale une requète entre le attach et le detach tout va foiré car hibernate util va lui retourner la session courante, non ?

    Même encadré par synchronise, si un autre utilisateur effectue une autre action cela va planté.

    Enfin voila, je pense que chaque strategie possède sa propre architecture et il n'existe pas une seule et unique solution, voici donc juste une proposition . (Perso, c'est aussi celle que j'utilise)
    Du coup c'est longue ou courte que tu utilises BisuR ?

    En plus de cette stratégie, il existe aussi des stratégies d'accès concurrentiel :
    1/ Optimiste avec champ date ou version. Obligatoire pour l'utilisation des sessions courtes puisque les verrous basiques de DB ne durent que lors de sessions/transactions il me semble, à moins que tu ne gères toi-même tes verrous.
    2/ Pessimiste. Ici, tu poses un verrou à chaque utilisation d'un objet dans le cadre de transactions atomiques.
    Si ca ne te deranges pas trop tu pourrais me detailler un peu cela, perso je n'ais pas compris ce que la doc expliquai. Pareil pour le N+1 select j'ai lu l'explication mais pas saisi réellement le problème et comment l'éviter ...

    Je suis un peu pénible sur le coup mais cela m'interesse réellement de comprendre (et pas juste pour mon projet actuel ).
    La posix attitude ...

  10. #10
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Citation Envoyé par K-Kaï
    mais toujours le même problème : la methode attach va ouvrir une session, sans la fermer (pour garder l'objet attaché) et la methode detach va fermer cette session. J'ai bon ??
    Le bout de code que j'affichais proposait plutot une solution de session synchronisée avec la requete HTTP donc en gros, ta servlet gère le debut et la fin des sessions ainsi que l'attachement/detachement des objets (qui peut aussi bien etre traité dans le manager lors de la creation de la session ... dans ce style :

    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
    //dans la servlet
    manager.startSession(mesobjets);
    //...
    manager.closeSession(mesobjets2);
    [...]
    //dans le manager
    public void startSession(ArrayList objets){
       session = pm.startSession();
       session.merge(objets);
    }
     
    public void closeSession(ArrayList objets){
       session.evictAll(objets);
       session.close();
    }
    Je ne garantis pas l'exactitude des appels de fonctions, je n'utilise pas encore celles-ci

    Citation Envoyé par K-Kaï
    Or dans une appli comme la mienne (plein de threads : webapps) cela se gere comment ?
    Vois avec _beber85 qui propose une réelle solution avec sessions courtes et lazy loading

    Citation Envoyé par K-Kaï
    donc si jamais quelqu'un intercale une requète entre le attach et le detach tout va foiré car hibernate util va lui retourner la session courante, non ?
    Dans ma méthode non car en faisant manager.startSession(), tu crées la session courante dans le manager et, c'est à l'aide de celle-ci que tu vas réaliser tes operations. Cette session se terminera via le closeSession()...
    entre les deux les objets auront été rattachés a la base pour cette session

    Citation Envoyé par K-Kaï
    Du coup c'est longue ou courte que tu utilises BizuR ?
    Perso, je suis actuellement sur les sessions longues, mais, dans le cadre de mon travail de R&D, je vais sillonner toutes les possiblités lors des prototypages.

    Cette solution proposée s'assimile à des sessions courtes puisque je détache les objets mais les sessions ici présentes sont moins atomiques que celles de _beber85.

    Citation Envoyé par K-Kaï
    Si ca ne te derange pas trop tu pourrais me detailler un peu cela, perso je n'ais pas compris ce que la doc expliquai. Pareil pour le N+1 select j'ai lu l'explication mais pas saisi réellement le problème et comment l'éviter ...
    Le principe d'accès concurrentiel rentre dans le cadre de la conservation de l'intégrité des données en base. Autrement dit, comment être sur d'avoir le bon état d'un enregistrement lorsque je le modifie ? n'a t il pas été modifié par quelqu'un d'autre entre le temps où je l'ai récupéré en base et le moment ou je le met à jour ?

    Selon les applications (multi utilisateurs ou non des données), tu devras mettre en place une stratégie d'accès concurrentiel ou non. Dans l'optique que ton appli servira pour une boite, on considerera qu'elle est multi utilisateurs (surtout si tu parles de thread en plus ). Dans ce cas, tu dois reflechir au moyen de gerer cette integrité des données.

    Hibernate te propose plusieurs solutions selon tes strategies :
    1/ pessismiste et verrous. A utiliser si tu mappes un systeme existant et non modifiable. Mais également si tu veux rester dans un esprit transactionnel comme avec les bases de données. (tu poses donc des verrous de lecture, modifications, etc. et les relache en fin de transaction). Surement plus adapté aux sessions longues.
    2/ optimiste et versionning. Hibernate te propose de le laisser gerer cela en ajoutant un champ a chacune de tes tables (un champ version ou date)
    3/ optimiste et versionning applicatif. Tu peux également gerer applicativement tes versions d'objets sans toucher à la base. ainsi, les utilisateurs utilisant les mêmes objets, gère applicativement un attribut version non persistant.

    Pour le N+1 select, c'est un point bien détaillé pr la doc Hibernate. Lorsque tu utilises le lazy loading :

    1/ Tu charges l'objet via une première requete (jusque la, normal).
    2/ Si il a une collection d'objets avec le lazy loading :
    2a/ Tu charges la liste des identifiants seulement (1 requete)
    2b/ Pour parcourir la liste d'objets, tu executes une requete a CHAQUE objet pour récuperer ses attributs (N requetes pour N objets dans la collection)

    Tu fais donc N+1 Select (requetes utilisant select en d'autres termes) pour charger un objet completement.

    Pour remédier à ce probleme d'optimisation (car ca coute cher tout ca dans le fond), ils proposent le batch-size qui charge par LOTS la collection (donc si tu définis un bath size a 5, tu feras N/5+1 select, ce qui est bien moindre déjà selon le nombre d'objets de la collection en moyenne) ou les plans (fetch group je crois) qui chargent totalement certaines associations (utilisé notamment pour les assos sans collections afin d'eviter une requete supplémentaire).

    Voila j'espere que ca te va comme explication...
    See you, space cowboy... and if you're satisfied, click on

  11. #11
    Membre actif
    Inscrit en
    Mai 2005
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 217
    Points : 220
    Points
    220
    Par défaut
    D'ailleurs au passage, j'ai un petit pb ..

    Pour re-attacher un objet, le merge deconne chez moi ... je dois utiliser le refresh :s

    Est ce que qq'1 à le meme pb ??

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    Bizur, tu pourrais me détailler la classe manager que tu utilse toout au long du message stp, car c'est un peu le principe que j'avais mis en place et cela m'interesserer grandement de voir comment elle est faite.
    La posix attitude ...

  13. #13
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Bon, voici les classes que j'utilise actuellement (inspirée dejà de quelqu'un qui m'a "lancé" sur Hibernate (de rien _beber85 ))


    Classe HibernateUtil :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    package com.dvlpt.util;
     
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
     
    public class HibernateUtil {
     
        private static final SessionFactory sessionFactory;
     
        static {
            try {
                // Crée la SessionFactory
                sessionFactory = new Configuration().configure().buildSessionFactory();
            }
            catch (HibernateException ex) {
                throw new RuntimeException("Problème de configuration : " + ex.getMessage(), ex);
            }
        }
     
        public static final ThreadLocal session = new ThreadLocal();
     
        public static Session currentSession() throws HibernateException {
            Session s = (Session) session.get();
            // Ouvre une nouvelle Session, si ce Thread n'en a aucune
            if (s == null) {
                s = sessionFactory.openSession();
                session.set(s);
            }
            return s;
        }
     
        public static void closeSession() throws HibernateException {
            Session s = (Session) session.get();
            session.set(null);
            if (s != null)
                s.close();
        }
    }
    Classe DAOManagerHibernate issue de IDAOManager
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    package com.devlpt.dao;
    //classes JDK
    import java.util.Collection;
    import java.util.Iterator;
    //classes Hibernate
    import org.hibernate.Session;
    //classes du projet
    import com.devlpt.util.HibernateUtil;
    
    public class DAOManagerHibernate implements IDAOManager {
    
        private static DAOManagerHibernate manager;
        private Session session;
        
        private DAOManagerHibernate(){};
    
        public static DAOManagerHibernate getInstance(){
            if (null==manager){
                manager = new DAOManagerHibernate();
            }
            return manager;
        }
        
        public void startSession(){
            session = HibernateUtil.currentSession();
        }
        
        public void closeSession(){
            HibernateUtil.closeSession();
            session=null;
        }
        
        public void startTransaction(){
            session.beginTransaction();
        }
        
        public void commit(){
            session.getTransaction().commit();
        }
        
        public void rollback(){
            session.getTransaction().rollback();
        }
        
        public void updateSession() {
            session.flush();
        }
        
        public void save(Object o) throws Exception {
            session.saveOrUpdate(o);
        }
        
        public void saveCollection(Collection c) throws Exception {
            for(Iterator it=c.iterator();it.hasNext();){
                session.saveOrUpdate((Object)it.next());
            }
        }
        
        public void delete(Object o) throws Exception {
            session.delete(o);
        }
        
        public void deleteCollection(Collection c) throws Exception {
            for(Iterator it=c.iterator();it.hasNext();){
                session.delete((Object)it.next());
            }
        }
        
    // et autres fonctions spécifiques à mon programme
    [...]
    }
    Comme je suis en prototypage, il y a pas mal de tests que je ne fais pas (par exemple, verifier que la transaction a commencé avant de commiter ...) du fait que je serai le seul à utiliser ces classes

    EDIT: Idem pour les envois d'exception, une classe d'exception ou un renvoi d'Hibernate Exception serait plus approprié sachant que j'utilise, pour ma part plusieurs frameworks, je ne peux donc etre trop précis dans le type d'Exception levée
    See you, space cowboy... and if you're satisfied, click on

  14. #14
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    et pour ce qui est du attach et detach, il faut preferer un merge ou un lock ?

    perso pour le moment c'est lock avec l'attribut UPGRADE.
    La posix attitude ...

  15. #15
    Membre éclairé Avatar de BizuR
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    688
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 688
    Points : 757
    Points
    757
    Par défaut
    Un LOCK avec du detachement ?!?

    Le lock permet de poser un verrou, il s'incrit dans une politique de sessions longues et traitements transactionnels, sauf si je me trompe (j'ai pas été verifié en fait).

    Pour le détachement, on utilise en règle générale evict(Object) ou evictAll(Collection).

    Pour le rattachement, il faut utiliser un merge(Object) pour le réintegrer a la base (mais il crée parfois des problèmes apparemment), il existe aussi le refresh() ou encore l'intégration dans une association ou l'autre partie est rattachée à la session
    See you, space cowboy... and if you're satisfied, click on

  16. #16
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    370
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2006
    Messages : 370
    Points : 223
    Points
    223
    Par défaut
    Nan nan le lock c'etait pour l'attachement, bien evidement evict pour detacher

    ok ok, oui c'est pareil pour moi, merge pose probleme et j'utilise refresh.

    Et est t'il penalisant de melanger des parties en transaction longues et d'autre fonction du manager en transaction courtes ?
    La posix attitude ...

  17. #17
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut fonctionnement du merge
    Bonjour
    suite à quelques problèmes j'ai pu comprendre (en partie) le fct du merge
    il est utile lorsqu'on gère les version d'un objet
    il faut noter que la fonction merge retourne l'objet mergé avec celui de la session (celui passé en parametre n'est pas modifié)


    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
     
    MyClass monObjet2 = session.get(MyClass, monObject.getId())
    if(monObjet2 != null)//l'objet est persistent dans la session
    {
      //le merge ne generera pas d'HibernateException
      try
      {
         monObjet2 = session.merge(monObjet)
      }
      catch (StaleObjectStateException ex)
      {
        //monObjet est dans une version antérieure à celle contenue 
        //dans la   version
        //à vous de régair en fonction
        //car monObjet2.getVersion() > monObjet.getVersion()
      }
    }

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

Discussions similaires

  1. [Session] Organisation du code et les Sessions
    Par sir_gcc dans le forum Autres composants
    Réponses: 3
    Dernier message: 03/01/2007, 21h49
  2. Organisation du code source
    Par _kal_ dans le forum C
    Réponses: 18
    Dernier message: 04/08/2006, 14h15
  3. organisation du code.
    Par poporiding dans le forum C++
    Réponses: 36
    Dernier message: 13/07/2006, 10h15
  4. organisation du code.
    Par poporiding dans le forum C++
    Réponses: 3
    Dernier message: 28/06/2006, 17h10
  5. Réponses: 4
    Dernier message: 19/09/2005, 17h56

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