These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 
Author Message
 Post subject: [Hibernate 3.2.5 / Criteria] pb rafraichissement
PostPosted: Wed Oct 31, 2007 11:56 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
Bonjour à tous,

Dans une application web Struts/Hibernate (Critéria) /Mysql, je rencontre le pb suivant :

J'implémente deux boutons
    - "save" : qui crée/met à jour un enregistrement en BDD, le recharge et l'affiche
    - "refresh" : qui recharge l'enregistrement à partir de la BDD


Mon pb repose sur le scénario suivant :
- Modification et sauvegarde d'un enregistrement (bouton "Save") : la donnée est correctement affichée, la base est correctement mise à jour
- rafraichissement de la donnée (bouton refresh) : les données affichées correspondent (aléatoirement) aux valeurs précédentes

Le cache coté client n'est pas en cause.
le cache de second niveau hibernate est désactivé en configuration
Le rechargement en BDD de mon objet se fait via la même méthode, que ce soit après l'enregistrement, ou pour le rafraichissement de mon objet
Les actions Struts se terminent systématiquement par un commit() final
L'enregistrement en base est déclenché par le commit de mon objet hibernate mis à jour (commit() fait avant le rechargement en BDD de la donnée)


Cela me fait penser à un pb de cache Hibernate..
J'ai essayé sans succès plusieurs méthodes pour forcer hibernate à recharger les données en base et/ou supprimer le cache hibernate :

Lors de la création de la session initiale
Code:
session = _sessionFactory.getCurrentSession();
session.setFlushMode( FlushMode.ALWAYS);
session.beginTransaction();
session.setCacheMode(CacheMode.IGNORE);
session.clear();


Lors de la requête de selection :
Code:
Criteria criteria = session.createCriteria(VocalMessage.class);
criteria
    .add(Restrictions.eq("id", a_vocalMessageId))
    .setLockMode(LockMode.READ);
VocalMessage curRecord = (VocalMessage) criteria.uniqueResult();
if(curRecord != null && !Utils.isEmpty(curRecord.getId())) {
      session.refresh(curRecord, LockMode.READ);
}



Auriez vous des idées ou des pistes pour résoudre ce pb ?
Merci bcp.

Patrick.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 05, 2007 8:05 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
J'ai exactement le même problème mais pas de solution.


Top
 Profile  
 
 Post subject: Nettoyer la session
PostPosted: Tue Nov 06, 2007 1:49 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
En faisant un session.clear() juste avant de commencer la transaction j'ai l'impression que le problème disparait


Top
 Profile  
 
 Post subject: Re: Nettoyer la session
PostPosted: Tue Nov 06, 2007 6:26 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
No-More wrote:
En faisant un session.clear() juste avant de commencer la transaction j'ai l'impression que le problème disparait


avant ou après le beginTransaction() ?


Top
 Profile  
 
 Post subject: ...
PostPosted: Tue Nov 06, 2007 6:40 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
Je le met juste après avoir récupérer la session et avant le beginTransaction.
Je le fais systématiquement.
Je ne sais pas si c'est la meilleur solution mais pour l'instant ça a l'air de fonctionner.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 06, 2007 8:24 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
Ça ne fonctionne pas pour moi..
Si tu le mets avant le beginTransaction, tu dois avoir une exception hibernate :
Code:
org.hibernate.HibernateException: clear is not valid without active transaction


Si ce n'est pas le cas, c'est que ta transaction est toujours active au moment ou tu fais ton beginTransaction.
Ton pb vient peut être de là.


Top
 Profile  
 
 Post subject: ...
PostPosted: Tue Nov 06, 2007 9:16 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
étrange ce que tu me dis,
je ne vois pas pourquoi j'aurais une transaction en cours, je termine toujours par un commit().

C'est un projet que j'ai repris donc possible que je sois passé à coté de certains détails surtout que je début sur hibernate.

Par contre il s'avère que c'est efficace chez moi je n'ai plus de problème avec hibernate de ce coté là mais j'aimerais bien trouver une solution plus propre.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 06, 2007 9:25 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
Effectivement, le clear va solutionner ton pb, car si ta transaction est active,
il fait l'équivalent d'un evict sur tous les objets de ta session.

par contre, si tu as des objets récupérés de la transaction précédente, ils ne seront plus rattachés à ta session..
il faudra passer par un update() ou un refresh() pour les rattacher ) la session.

Tu devrais peut être faire un truc du genre pour ton beginTransaction :

Code:
if(!session.getTransaction().isActive()) {
    session.beginTransaction();
}      


A verifier s'il ne faut pas faire le test aussi sur le wasCommitted() et le wasRolledBack()


Top
 Profile  
 
 Post subject: ...
PostPosted: Tue Nov 06, 2007 9:45 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
Merci pour les pistes que tu m'as fournies,

mais après avoir testé je n'ai pas de transaction active donc je ne vois pas pourquoi session.clear() fonctionne chez moi et pas chez toi.


Top
 Profile  
 
 Post subject: Re: ...
PostPosted: Tue Nov 06, 2007 10:08 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
No-More wrote:
Merci pour les pistes que tu m'as fournies,

mais après avoir testé je n'ai pas de transaction active donc je ne vois pas pourquoi session.clear() fonctionne chez moi et pas chez toi.


peut être pcq je récupérè ma session vi le getSessionFactory() et que ma session est automatiquement fermée par le commit()...
toi tu fais un openSession() ou pas ?


Top
 Profile  
 
 Post subject: ...
PostPosted: Wed Nov 07, 2007 1:53 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
La gestion des session et sessionFactory était en place avant que je prenne le projet.

Ce que je peux dire en regardant un peu le code, c'est qu'une seule sessionFatory est crée à l'initialisation. La session elle est stockée dans un thread et récupérée par une méthode qui vérifie si la session existe encore et qui la recrée seulement si ce n'est pas le cas. Cela évite de recréer des session trop souvent qui est un processus consommateur de ressource d'après ce que j'ai lu sur le net.

Je n'ai pas de session.close() sauf pendant le contextDestroy mais il arrive que la session se termine mais je ne sais pas vraiment pourquoi.

Code:
   public static final ThreadLocal session = new ThreadLocal();

   public static Session currentSession()
   throws Exception {

      Session s = (Session) session.get();
      // Ouvre une nouvelle Session, si ce Thread n'en a aucune
      if (s == null) {
         s = sessionFactory.openSession();
//         s.setCacheMode(CacheMode.IGNORE); // ne fonctionne pas
         session.set(s);
      }
      s.clear(); // j'ai rajouté le session clear ici pour éviter d'avoir à le rajouter partout dans le code
      return s;
   }


lorsque je veux faire une requete je commence toujours de cette façon :
Code:
            Session session = HibernateUtil.currentSession();
            tx = session.beginTransaction();

et je fini par un
Code:
tx.commit();

parfois j'utilise :
Code:
            session.flush();
            session.clear();
            tx.commit();


Je n'ai pas cherché à modifier la gestion des sessions mais il doit surement avoir des méthodes plus efficaces.


Top
 Profile  
 
 Post subject: Re: ...
PostPosted: Tue Nov 13, 2007 8:57 am 
Newbie

Joined: Fri Oct 26, 2007 9:51 am
Posts: 9
Ca y est,
j'ai enfin trouvé la cause de mon pb....
c'est en fait tout simple une fois qu'on a trouvé....

Je me suis rendu compte qu'il restait des transaction non fermées sur la base..
Dans certains cas, je faisait un commit, suivit plus loin d'une méthode pour récupérer une liste d'infos en base.
A l'issue du commit, la session est automatiquement fermée avec la transaction. Par conséquent le Session session = Factory.getCurrentSession() de la méthode appelée, génère une nouvelle session et une nouvelle transaction. A l'issue de la méthode, la variable "session" est détruite, mais ce n'est pas le cas de la transaction ni de la session hibernate qui reste attachée au thread tomcat.

Lors d'une action struts ultérieure, si je récupère ce thread, je retrouve également la session toujours ouverte qui y est attaché... et donc les objets hibernate correspondants, avec des données non à jour.

Je ne comprend toujours pas pourquoi même dans ce cas les refresh ou lockMode.READ n'ont pas forcé une relecture depuis la BDD, mais la chasse aux session ouvertes à résolu mon pb.

De la même façon, chaque catch() fait également un rollback de la transaction en cours, de manière à ne pas laisser de transaction en cours sur la base...


Top
 Profile  
 
 Post subject: Merci pour la solution
PostPosted: Tue Nov 13, 2007 9:04 am 
Newbie

Joined: Mon Nov 05, 2007 1:52 am
Posts: 9
Effectivement je suis dans le même cas que toi (j'accède à des données de mes objets en dehors de la transaction).

Ca explique tout.

Merci bonne continuation.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.