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 des collections


Sujet :

Hibernate Java

  1. #1
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut Persistance des collections
    Bonjour,

    Je dispose d'une classe Tournoi qui contient un ensemble de matches (Set<Match> matches).

    Lorsque j'ajoute un match au tournoi, j'instancie un nouvel objet Match puis je l'ajoute au Set et enfin je le sauvegarde dans la base :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tournoi.addToMatches(newMatch);
    session.save(newMatch);
    sachant que le corps de "addToMatches" est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public void addToMatches(Match match) {
    		if (this.matches == null)
    			this.matches = new java.util.HashSet<Match>();
    		this.matches.add(match);
    	}
    Cependant, dans une autre classe, je fais appel à une requête qui ne récupère que des matches correspondant à certains critères puis j'apporte des modifications sur ces matches et je fais un update().

    Ainsi, la collection "matches" associée au "tournoi" n'est plus synchronisée avec la base.

    Faut-il faire constamment un "refresh" ?
    Est-ce un problème que les instances java ne soient pas toujours synchronisées avec la base ?
    Y a-t-il une stratégie particulière à adopter car je trouve qu'il est extrêmement difficile de maintenir les objets java synchronisés avec la base ?

    J'ai par ailleurs une autre question concernant la performance. Supposons que je souhaite mettre à jour le Set de matches qui est associé au tournoi.
    Vaut-il mieux parcourir les éléments un par un et faire un update sur chacun d'eux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (Match match : matches ) {
    session.update(match);
    }
    ou bien faire un appel à update sur l'objet tournoi afin qu'il mette à jour le set par cascade :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tournoi.setMatches(matches);
    session.update(tournoi)
    sachant qu'hibernate cherchera à faire la mise à jour sur les autres associations de Tournoi (cascade=all) ?

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Par défaut
    Le principe de base c'est quand tu veux faire des modifications, tu ouvre une transaction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Transaction tx = session.beginTransaction();
    Et quand tu as fini tu la committe :
    C'est au moment du commit que Hibernate synchronise les changements apportés avec la base.

    Si tu es dans un envirronnement managé (EJB...) la transaction est gérée automatiquement.

    Quand tu procède comme ça tu as juste besoin de faire des save() pour les nouvelles instances créées. Le update() est à utiliser dans le cas où tu as une instance détachée, c'est à dire une instance qui vient de la base (elle a une id) mais n'a pas été obtenue via la session courante.

    Le refresh est à utiliser quand tu sais que les données ont été modifiées dans la base (par ex. par un trigger) mais que la session ne le sait pas encore

    Sinon pour ta méthode addToMatches(), j'ajouterai match.setTournoi(this)

  3. #3
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Je n'ai pas précisé l'ouverture et la fermeture des transactions car j'utilise Spring pour la gestion des transactions (avec une couche service et dao).

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Par défaut
    Je dirai que le problème vient de ta gestion des transactions alors. Essaie de faire afficher les requêtes SQL pour voir si ça fait ce que tu penses

  5. #5
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Je crois que tu n'as pas compris mon problème.

    En fait, lorsque je fais une requête à l'aide de "Criteria" afin de récupérer une liste de matches selon certains critères, je récupère de nouvelles instances de mes objets match. Ainsi en apportant des modifications sur ces derniers, cela n'affectera en aucun cas la liste de matches initialement associée à l'objet "Tournoi".

    Je trouve donc que c'est très pénalisant au niveau performance si on souhaite constamment avoir les objets java synchronisés avec la base de données.

    Dans mon cas, il faudrait que je remplace certains matches de la liste associée à l'objet "Tournoi" par ceux issus de la requête.

    Alors à ce moment j'aurais mon objet java synchronisé avec la BD.
    Mais il aura fallu comparer chaque objet de la liste de matches associée au Tournoi par ceux de ma requête.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Par défaut
    Je crois que tu n'as pas bien lu ma réponse

    Au milieu d'une transaction, la base n'est pas synchronisée : les opérations SQL ne se font qu'à la fin de la transaction. Donc si tu fais une requête SQL au milieu, tu auras les données du début de la transaction.

    Si tu as besoin de synchroniser la base en cours de transaction tu peux faire session.flush(); à ce moment Hibernate prend tous les objets qui ont été modifiés et les updates, prend tous les objets passés à save(...) et les insére et prend les objets passés à delete(...) et les supprime. En tout cas le update ne sert à rien.

  7. #7
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Apparemment, on ne se comprend pas

    Je n'ai aucun problème à récupérer des données fraichement insérées dans la BD.
    Je mets à jour et je lis les données de la base sans aucun souci.

    Je reprends ma question.

    Initialement, je construis un objet Tournoi auquel je lui associe une collection de matches puis j'insère l'objet Tournoi dans la BD. J'ai alors mon objet ainsi que ses collections synchronisés avec la BD.

    Plus tard, dans une autre classe, j'effectue une requête à l'aide de la classe Criteria afin de ne récupérer que des matches de la journée 1. Ensuite, je modifie ces matches en leur affectant un résultat et je les mets à jour dans la BD.

    A ce moment, j'ai apporté des modifs aux matches issus de ma requête mais entretemps, mon objet Tournoi n'a absolument pas changé.
    Si je parcours la collection des matches, j'ai toujours mes matches dans leur état initial (sans score) mais ceci est tout à fait normal du fait que j'ai récupéré de nouvelles instances de l'objet Match et apporté des modifs sur l'instance de ces objets.


    Pour avoir ma collection de matches à jour, il faudrait que je remplace certains matches de la liste associée à l'objet "Tournoi" par ceux issus de la requête (instances auxquelles j'ai apporté des modifs).

    Alors à ce moment j'aurais mon objet java synchronisé avec la BD.
    Mais il aura fallu comparer chaque objet de la liste de matches associée au Tournoi par ceux de ma requête.

    J'espère avoir été plus clair

  8. #8
    Membre confirmé Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Par défaut
    Pourquoi ne pas recharger le Tournoi avec ton DAO directement aprés avoir fait les modifications sur les matchs ? (méthode de bourrin ? )

  9. #9
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    Citation Envoyé par KneXtasY
    Pourquoi ne pas recharger le Tournoi avec ton DAO directement aprés avoir fait les modifications sur les matchs ? (méthode de bourrin ? )
    J'ai déjà essayé de faire un refresh mais hibernate fait pas mal d'opérations et c'est très long.

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Par défaut
    C'est que tu fais les opérations dans des sessions différentes. Si je prend cet exemple :

    - session 1 : charger tournoi #1
    - session 2 : charger tournoi #2 et le modifier
    - session 1 : ne voit pas les modifications de session 2

    Je ne sais pas trop ce que tu cherches à faire mais a priori si tu t'attends à voir tes modifications tu devrais avoir une même session pour ces différentes opérations.

    En fait pour chaque instance d'une entité, il y aura autant d'instances d'objet Java que de session, et ces instances Java ne sont pas synchronisées entre elles. Sinon dans un serveur tu aurais des objets qui "bougent tout seuls" au cours de requêtes.

  11. #11
    Membre confirmé
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Par défaut
    J'utilise Spring qui me gère automatiquement les transactions.
    En ce qui concerne la session, mes DAOs appellent "sessionFactory.getCurrentSession()".

    Je crée un tournoi en initialisant ses matches. Je le rends persistant dans la base.
    Dans une autre classe je récupère uniquement les matches d'une journée, pour un affichage par journée. L'utilisateur peut modifier un match à la fois.
    Cette modification est répercutée dans la BD.

    L'instance de tournoi n'a pas changé (notamment la collection des matches).
    Si je souhaite que mon objet reste synchronisé après cette opération, est-ce que j'appelle "refresh" ? Ou dois-je recharger l'objet tournoi à partir de la bd ?

    Tournoi contient notamment une collection "Classement" et lorsque je souhaite recalculer celui-ci puis le mettre à jour dans la BD, je voudrais appeller update sur l'objet Tournoi au lieu de parcourir la collection Classement et faire autant d'appels à update qu'il y a d'itérations. Cela semble bien plus coûteux en temps.
    Cependant, le problème est que si j'appelle update sur le Tournoi (la collection des matches contenant les objets sans les modifs de l'utilisateur), ces modifs sont écrasées par l'état des matches initiaux dans la BD.

    Quelle devrait être la bonne pratique ? Doit-on toujours avoir les instances java synchronisées avec la BD ou pas forcément ?

Discussions similaires

  1. Persistance des objets : comment ?
    Par SteelBox dans le forum C++
    Réponses: 1
    Dernier message: 28/11/2005, 21h47
  2. Réponses: 1
    Dernier message: 03/10/2005, 14h46
  3. [Struts][DynaActionForm et persistance des objets]
    Par jcos dans le forum Struts 1
    Réponses: 4
    Dernier message: 22/12/2004, 09h15
  4. Persistance des données en mémoire
    Par giviz dans le forum Architecture
    Réponses: 13
    Dernier message: 21/12/2004, 09h44
  5. [Strategie]persistance des données
    Par altropus dans le forum Persistance des données
    Réponses: 6
    Dernier message: 04/11/2004, 04h36

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