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 :

[Hibernate 3] Les collections sont-elles toujours sauvegardées ?


Sujet :

Hibernate Java

  1. #1
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut [Hibernate 3] Les collections sont-elles toujours sauvegardées ?
    Bonjour,

    Dans une application, j'ai une relation 1-* entre deux entités. Voici un peu l'extait des fichies .hbm.xml :

    Le "Père"

    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
    <hibernate-mapping>
    	<class
    		name="Attestation"
    		table="ATTESTATION"
    	>
    		<meta attribute="sync-DAO">false</meta>
    		<id
    			name="Id"
    			type="string"
    			column="CODEPARENT"
    		>
     
    		<list name="DetailsAttestations" inverse="true">
    			<key column="CODEDETAIL"/>
    			<one-to-many class="DetailsAttestation"/>
    		</list>
     
     
    	</class>	
    </hibernate-mapping>
    le fils :

    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
    <hibernate-mapping>
    	<class
    		name="DetailsAttestation"
    		table="DETAILS"
    	>
    		<meta attribute="sync-DAO">false</meta>
    		<id
    			name="Id"
    			type="string"
    			column="CODEDETAIL"
    		>
    			<generator class="assigned"/>
    		</id>
     
    		<many-to-one
    			name="Attest"
    			column="CODEPARENT"
    			class="Attestation"
    			not-null="true"
    		>
    		</many-to-one>
     
     
    	</class>	
    </hibernate-mapping>
    Pratiquement, dans le code, voici ce qui se passe :
    - J'ai une fiche qui list tous les parents. Je peux utilisr un bouton pour ajouter un nouveau parent. En réalité, les données sont chargées dans un JTable.
    - Dans la fiche d'un parent, j'ai un bouton pour valider les infos sur lui (le parent), des champspour ses infos et un autre JTable où sont chargées la liste des enfants
    - Lorsque je charge la fiche du parent, j'instancie une session à partir d'une classe utilitaire (un singleton) prévue pour cà => la session est fermée quand la liste est recupérée et puis je charge mes données dans la table
    - De même, dans la fiche parent, quand je clique sur "Ajouter un Enfant", une nouvelle session est instanciée.
    - Une fois que je valide les données dans la fiche enfant, présentément, je fais deux choses :
    1) persister l'enfant avec un appel à session.save
    2) ajouter l'enfant dans la liste du parent (les enfants sont dans une liste comme précisés dans le fichier de mapping)

    Vu que je n'utilise pas la même session, je voulais savoir si j'ai besoin de sauvegarder chaque enfant ou bien si un appel à session.save(objParent) sauvegardera en cascade les enfants. De même, je voudrai savoir si un appe à session.get(objParent) charge et instancie automatiquement tous les objets enfants.

    Merci.

    PS : après avoir lu la FAQ sur le sujet, j'ai lu que la méthode saveOrUpdate pouvait être utilisée pour rattacher automtiquement un objet à une autre session eteffectuer le traitement approprié. C'est bien cela?

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Par défaut dans Hibernate 3, les collections sont en mode lazy="true", donc ne sont pas chargées à la récupération de l'objet père.

    Si tu veux appliquer la sauvegarde en cascade, utilise dans le mapping de ta liste; l'attribut cascade, que tu peux mettre à all par exemple.

  3. #3
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut
    Merci de ta réponse

    Donc je dois modifier mon fichier de mapping comme ceci (extrait du parent) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <list name="DetailsAttestations" inverse="true" cascade="all">
    		<key column="CODEDETAIL"/>
    		<one-to-many class="DetailsAttestation"/>
    </list>
    ?

    Pour les collections, il y'a un avantage à utiliser une collection paticulière comme le set, map, etc ?

    De cette façon, dans la fiche enfant, dans le boutton "Valider", je n'ai plus besoin de faire un appel à save alors ? Je dois utiliser save ou saveOrUpdate ? Je pose la question parce que les objets ne sont pas recupérés par la même session.

    Merci

  4. #4
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    L'utilisation de telle ou telle collection dépend de tes besoins.
    Le type Set convient en général bien, car on ne peut pas avoir deux fois le même objet dans un Set, ce qui correspond bien aux bases de données.
    Cependant, je préfère utiliser une list ou un bag pour les applications Swing, car ces collections sont indexées et donc l'accès à l'objet est plus simple dans le cas de l'utilisation d'une JTable.

    Ta modification de mapping me semble correcte, à tester tout de même, en choisissant dans la documentation Hibernate, l'option de cascade qui t'arrange.

    Tu peux faire un saveOrUpdate du père, qui devrait logiquement enregistrer les modifications. (si tu as fait avant un : pere.getEnfants().add(enfant))

  5. #5
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut
    Je vais tester pour le "paramètre" cascade.

    Je fais bien un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pere.getEnfants().add(enfant)
    quand l'objet est nouveau (donc quand j'ai cliqué sur "Créer un enfant"). J'ajoute l'enfant dans la collection de cette façon.

    Donc, comme tu dis, à priori,cà devrait aller. Je vais mettre en commentaire les sauvegardes de l'enfant et voir si la seule sauvegarde du père enregistre tout le monde.

    Maintenant, au chargement, je dois avoir

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <list name="DetailsAttestations" inverse="true" lazy="false" cascade="all">
    		<key column="CODEDETAIL"/>
    		<one-to-many class="DetailsAttestation"/>
    </list>
    pour que la collection des enfants soient également chargées alors ?

  6. #6
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    En fait, il n'est pas recommandé de mettre lazy="false" dans le mapping, car dans certains cas, tu risques de "remonter" beaucoup de données.
    Cela, va fonctionner, mais ce n'est pas recommandé.

    Il est préférable de paramétrer le chargement des objets, selon les besoins.
    Pour cela, soit tu fais un parent.getEnfants(), une fois le parent récupéré.
    Ca devrait charger la collection.

    Soit, tu récupères le parent via une requête HQL en utilisant l'attribut join fetch pour charger ta collection.

    Soit, tu récupères le parent via une requête Criteria en utilisant également l'attribut fecth pour charger ta collection.

  7. #7
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut
    Citation Envoyé par fr1man
    Soit, tu récupères le parent via une requête Criteria en utilisant également l'attribut fecth pour charger ta collection.
    Excuse moi ... mais je pourrai avoir un exemple ? Lorsque je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s.createCriteria(obj.getClass())
    je vois biens un truc pour définir la taille du "fetch" (setFetchSize) mais tu ajoutes l'attribut fetch là comment stp ?

  8. #8
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Parent parent= (Parent) session.createCriteria(Parent.class)
                    .setFetchMode("enfants", FetchMode.JOIN)
                    .add( Restrictions.idEq(parentId) )
                    .uniqueResult();

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Il y a encore une option que j'avais oubliée pour charger une collection:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Hibernate.initialize(parent.getEnfants());

  10. #10
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut
    Merci

    Je vais adopter la première approche qui est plus "lisible".

    Merci, ce problème de charger les enfants me posaient un réel problème

    Sujet résolu en moins d'une heure ! Vive fr1man

  11. #11
    Rédacteur
    Avatar de Giovanny Temgoua
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    3 830
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 3 830
    Points : 4 006
    Points
    4 006
    Par défaut
    "enfants" est bien le nom de la collection de Parent n'est ce pas ?

    Comme dans le système, je risque avoir à utiliser cette méthode à plusieurs endroits et comme le nombre de collections varie par objet, je cherche une méthode générique qui vas me charger toutes les collections de l'objet en question.

    Voici comment j'ai adapté le code à partir de ton code (j'ai modifié directemen dans le message):

    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
    public class LoadCollections<T>
    {
      private static Criteria addFetchMode(Criteria criteria, FetchMode mode, String collectionName)
      {
          return criteria.setFetchMode(collectionName, mode);
      }
      public static T loadCollections (Session session, String[] collectionsNames, T parent, String id)
      {
        Criteria criteria = session.createCriteria(T.class);
     
         for(int i = 0; i < collectionsNames.length; i++)
         {
             criteria = addFetchMode(criteria, FetchMode.JOIN, collectionsNames[i]);
         }
       return (T) criteria.add( Restrictions.idEq(parentId) ).uniqueResult();
      }
    }
    A l'appel cà donnerait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LoadCollections<ClassParent>.loadCollections(session, new String[]{"enfants1", "enfants2"}, instanceDeParent, "12d")
    A vu d'oeil, cà semble marcher non ?
    Je n'ai pas encore tester.

    En v2, je prévoit une méthode pour associer un FetchMode donné à une collection donnée...

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

Discussions similaires

  1. Quand les ressources sont elles associées ?
    Par poulette3000 dans le forum Windows
    Réponses: 1
    Dernier message: 25/08/2006, 23h57
  2. Réponses: 11
    Dernier message: 06/06/2006, 15h04
  3. Réponses: 3
    Dernier message: 01/05/2006, 15h09
  4. Réponses: 9
    Dernier message: 16/01/2006, 15h16
  5. Réponses: 2
    Dernier message: 30/10/2003, 00h47

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