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]comprendre la cache sur hibernate


Sujet :

Hibernate Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut [Hibernate]comprendre la cache sur hibernate
    Bonjour,

    J'ai développé une application web en utilisant hibernate. Seulement j'ai eu quelque probleme d'affichage lorsque je listais le contenu de ma base c'est à dire que cela ne correspondait pas du tout au contenu parfois mes modifications n'apparaissaient en bref.

    Afin de comprendre cela, j'ai testé toute les méthode comme flush save connect().commit().

    Et je me suis rendu compte qu'en fait il y a d'abord une ecriture dans le cache d'hibernate puis une écriture base.

    Je m'interroge par contre sur le cache d'hibernate.

    Est ce que le cache est rattache à une session ou est ce que plusieurs sessions partage le même cache?
    Car comme j'utilise tomcat et que tomcat est multi thread alors je me pose des questions sur les sessions et le partage du cache?

    Merci de vos réponses



    [Modéré par Didier] : ajout de tag dans le titre - Les règles du forum Java

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 274
    Par défaut
    Bonjour,

    Effectivement cela se passe en deux phases.
    il y a d'abord l'écriture dans le cache de premier niveau (cache de session ) lors d'un save, update, find, etc... puis ecriture si besoin dans la base lors du commit des transactions.

    Le cache de premier niveau est propre à une session et non partagé par celles ci, les données du cache sont mises à jour avec la base lors de certaines opérations. Ou alors le cache est vidé.

    La Session exécute parfois les ordres SQL nécessaires pour synchroniser l'état de la connexion JDBC avec
    l'état des objets contenus en mémoire. Ce processus, flush, se déclenche :
    • à certaines invocations de find() ou d'iterate()
    • à l'appel de net.sf.hibernate.Transaction.commit()
    • à l'appel de Session.flush()
    Dans ton cas il est probable que tu utilise des sessions différentes pour mettre à jour les données et pour les consulter.

    En modifiant le niveau de log tu verras toutes les opérations Hibernate y compris celles du cache et tu pourras voir si les données sont récupérées dans la base ou pas.

  3. #3
    Membre chevronné
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Par défaut
    Pourquoi un tel cache ? La réponse nous est donnée par Martin Fowler avec le pattern Unit of Work. Son livre est également un bon point de départ pour comprendre comment sont implémentés les différents outils d'ORM.

    Concernant Hibernate :
    - SessionFactory est un objet threadsafe et tu as juste besoin d'une instance partagée dans ton application,
    - l'objet Session n'est pas treadsafe et ne doit pas être partagé.

    Le cache de premier niveau est associé à la session (et donc non partagé).
    Si je me souviens bien, le cache de second niveau est associé à l'instance de SessionFactory (donc partagé).

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    je suis d'accord avec ca mais quand on lance tomcat il lance au moins 10 thread j'ai l'impression alors qu'il y autant de session qu'il ya de threads.

    j'ai fait un test avec deux threads dont chaque thread a sa propre session.
    Ce qui m'a étonné c'est que si j'écrit des données dans la session 1
    sans les commiter mais je l'ai flush pour mettre a jour la session (donc j'ai comme id 1 et 2). Dans la session 2 j'ai ecrit une donnée l'id qu'hibernate m'a attribué est 3. Je trouve cela etonnant car je croyais que les sessions ne communiquaientt pas.

    Par contre quand je liste les objet depuis la session 1
    j'obtient comme id 1 et 2
    et depuis la session 2
    j'obtient comme 3

    J'ai l'impression que parfois ca communique et parfois non

    Vous pouvez m'expliquer ?

    Merci

    et merci de m'avoir répondu

  5. #5
    Membre confirmé
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Par défaut
    je suis pas sur mais
    si tu flush ta session1, alors il demande au sgbd d'attribuer une pk
    de meme pour la session 2, c la bd qui attribut l'id, pas la session

    par contre si tu ne fais pas de commit, c bizar ou on a pas tout compris!

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    Je rapelle que j'ai un tableau de thread dans lequel j'associe a chaque thread une session
    Le but est de voir si les session communique entre elle ou si il y a partage du cache.
    Normalement non, mais les résultats que je montre un peu plus bas sont etonnant

    Et a vrai dire je ne comprend plus rien
    Donc si quelqu'un pourrait m'expliquer cela


    Non je ne fais de commit je fais que du flush
    le commit vient au dernier moment

    Voila le résultat que j'ai comme résultat
    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
     
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 1 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 1 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 2
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 3
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 2 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 2 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 4
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 2
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 3
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Voici ma fonction d'écriture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	public void ecrire(String title)
    	{
    		System.out.println(title + " Ecriture");
    		Utilisateurs _u = new Utilisateurs();
    		_u.setAge(26);
    		_u.setNom("Ujoodha");
    		_u.setPrenom("Vickrame");
    		_u.save(session);
    	}
    et le save
    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
     
       public void save(Session session)
        {
        	//Session session= null;
        	Transaction tx = null;
     
        	try {
    			//session = HibernateUtil.currentSession();
        		//session = HibernateMultiSession.currentSession();
    			if( !(session.isOpen() ) )
    				session.reconnect();			
    			tx = session.beginTransaction();
     
    			session.saveOrUpdate(this);
    			session.flush();
    			//session.connection().commit();
     
    			//return true;
    		} catch (HibernateException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    			try {
    				if(tx != null)
    					tx.rollback();
    			} catch (HibernateException e1) {
    				// TODO Auto-generated catch block
    				e1.printStackTrace();
    			}
    			//return false;
    		} 
    //		catch (SQLException e) {
    //			// TODO Auto-generated catch block
    //			e.printStackTrace();
    //		}
    //		finally{
    //			try {
    //				if(session != null)
    //				session.close();
    //			} catch (HibernateException e) {
    //				// TODO Auto-generated catch block
    //				e.printStackTrace();
    //			}
    //		}
        }
    [/code]

  7. #7
    Membre confirmé
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Par défaut
    essaie de faire un rollback de la session 1 apres la création dans la session 2
    puis un commit sur la session2

    juste pour voir si les pk vont changer

    si tu as pk= 1 & 4 alors hibernate se fie au sgbd
    si tu as pk=1,2 alors ???

    perso je pense que les sessions communiquent avec l'instance hibernate pour gérer les pk sans faires de requetes sans arret avec la base

    mais on, a n'engage que moi, et je debute avec hibenate donc... !!!!

  8. #8
    Membre chevronné
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Par défaut
    Quelle base de données utilises tu ? Si tu utilises MySQL, as tu ajouté type=InnoDB dans la déclaration de ta table ?

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    j'utilise hibernate v2.1 postgresql 8.3 et java 1.5

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    j'ai fait le rollback() comme tu me l'a suggere
    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
     
    	public static void test2()
    	{
    		// TODO Auto-generated method stub
    		Thread [] t = new Thread[] {new ThreadWrite(),new ThreadWrite()};
     
    		((ThreadWrite)t[0]).lire("\t Thread 1");
    		((ThreadWrite)t[0]).ecrire("\t Thread 1");
    		((ThreadWrite)t[0]).ecrire("\t Thread 1");
    		((ThreadWrite)t[0]).lire("\t Thread 1");
     
    		((ThreadWrite)t[1]).rollback("\t Thread 2");		
    		((ThreadWrite)t[1]).ecrire("\t Thread 2");
     
    		((ThreadWrite)t[1]).lire("\t Thread 2");		
    		((ThreadWrite)t[0]).lire("\t Thread 1");
     
    		((ThreadWrite)t[1]).commit();
    		((ThreadWrite)t[0]).commit();
     
    		((ThreadWrite)t[0]).closeSession();
    		((ThreadWrite)t[1]).closeSession();		
    	}
    Comme tu peux le voir les commits sont fait longtemps apres car je veux voir les sessions communiquent entre elles.
    Et j'obtient le résultat suivant
    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
     
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 1 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 1 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 2
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 3
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 2 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 2Rollback()
    	 Thread 2 Ecriture
    Hibernate: insert into utilisateurs (nom, prenom, age, id) values (?, ?, ?, ?)
    	 Thread 2 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 4
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 1 Lecture
    Hibernate: select utilisateu0_.id as id, utilisateu0_.nom as nom, utilisateu0_.prenom as prenom, utilisateu0_.age as age from utilisateurs utilisateu0_
    Id 1
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 2
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    Id 3
    Nom Ujoodha
    Prenom Vickrame
    Age 26
    	 Thread 2Commit()
    	 Thread 1Commit()
    Moi ce que je trouve bizar c'est j'ai l'impression que les session communiquent entre elles pour une écriture mais pas pour la lecture

    Est ce que qq1 partage cet avis ou je me trompe completement ou ??

    Merci de m'avoir répondu

  11. #11
    Membre chevronné
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Par défaut
    Citation Envoyé par mauvais_karma
    perso je pense que les sessions communiquent avec l'instance hibernate pour gérer les pk sans faires de requetes sans arret avec la base
    Au moment du save(), hibernate va demander à la base d'incrémenter la séquence pour obtenir l'id.
    Le fait que tu sois en mode READ_COMMITED et que les éléments avec l'id 2 &3 ne soient pas visibles depuis le thread 2 prouve que tout fonctionne normalement. La 2eme session ignore le contenu de la première. Elle sait juste que certains éléments de la séquence ont été attribués et prend les suivants.

    PS : ta trace n'est pas très claire

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    Donc cela voudrait dire la base de donnée a aussi un cache pour s'assurer de l'attibution des id ?

  13. #13
    Membre chevronné
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Par défaut
    Explique ce que tu veux dire, je ne comprends pas.

    Pour moi, tout semble fonctionner normalement.

  14. #14
    Membre confirmé
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Par défaut
    oui ca fonctionne correctement dans ce cas.

    moi je sugerai de faire un rollbacke de session 1 apres une insertion dans session2:


    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
     
       public static void test2()
       {
          // TODO Auto-generated method stub
          Thread [] t = new Thread[] {new ThreadWrite(),new ThreadWrite()};
     
          ((ThreadWrite)t[0]).lire("\t Thread 1");
          ((ThreadWrite)t[0]).ecrire("\t Thread 1");
          ((ThreadWrite)t[0]).ecrire("\t Thread 1");
          ((ThreadWrite)t[0]).lire("\t Thread 1");
     
    // pk de s1 = 1 , 2 et 3
     
    [b]      ((ThreadWrite)t[1]).ecrire("\t Thread 2");
    // pk de s2 = 4
          ((ThreadWrite)t[0]).rollback("\t Thread 1");[/b]      
    // 2 & 3 ne sont pas commité
     
          ((ThreadWrite)t[1]).lire("\t Thread 2");      
          ((ThreadWrite)t[0]).lire("\t Thread 1");
     
          ((ThreadWrite)t[1]).commit();
          ((ThreadWrite)t[0]).commit();
     
          ((ThreadWrite)t[0]).closeSession();
          ((ThreadWrite)t[1]).closeSession();      
       }

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 135
    Par défaut
    C'est simplement un test que je fais afin de bien comprendre la notion de session et de cache.

    Par contre j'aurai une autre question concernant la fermeture de la session il est recommende d'après la doc hibernate de femer la session apres chaque requete.
    En en pratique je remarque que personne ne le fait ni même moi.

    Si on fait on flush et commit toujours et que l'on fait un rollback() lors d'une erreur quelles sont les risques que l'on peut avoir si on laisse la connection toujours ouverte.

  16. #16
    Membre chevronné
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Par défaut
    J'aimerais savoir où tu as vu qu'il fallait fermer la session après chaque requête...

  17. #17
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 274
    Par défaut
    Bonjour,

    à mon avis les seuls risques de laisser une session Hibernate ouverte sont une dégradation des performances au fur et à mesure que le cache de session augmente.

    Mais celà dépend de la politique de gestion de session Hibernate (une session par utilisateur, par transaction, etc..) et si l'utilisation de l'application est intensive ou pas.

    ce problème peut être résolu avec un timeout de session http ou un redémarrage du serveur tous les jours.

Discussions similaires

  1. Hibernate et le cache
    Par titeuf92 dans le forum Hibernate
    Réponses: 6
    Dernier message: 07/12/2006, 16h15
  2. Questions sur Hibernate
    Par errant dans le forum Hibernate
    Réponses: 3
    Dernier message: 27/03/2006, 14h18
  3. Réponses: 4
    Dernier message: 13/02/2006, 11h34
  4. [Hibernate]Question sur Hibernate
    Par elhani dans le forum Hibernate
    Réponses: 2
    Dernier message: 30/12/2005, 15h39
  5. [Hibernate] Gérer le cache L2
    Par mauvais_karma dans le forum Hibernate
    Réponses: 2
    Dernier message: 30/08/2005, 11h50

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