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 :

LazyInitializationException en présence d'une session active


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut LazyInitializationException en présence d'une session active
    Bonjour à tous !

    Je rencontre actuellement un problème avec le lazy-loading d'hibernate.
    J'obtiens l'exception suivante lorsque je souhaite accéder aux données d'une collection :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: fr.habipro.crm.models.Groupe.societes, no session or session was closed
    Pour situer un peu le contexte je développe un client lourd en J2SE et je manipule des objets de type Societe qui contiennent différentes informations sur des sociétés.

    Je dispose d'une fenêtre qui m'affiche la liste des sociétés et quand je double clique sur un enregistrement j'ai une fenêtre d'édition qui s'ouvre à la place (grâce à un CardLayout).

    Chaque fenêtre dispose de sa propre session qui est ouverte/fermée en fonction des évènements componentShown() et componentHide().

    J'utilise également une Classe Groupe qui contient une liste de sociétés.

    Parallèlement à ça j'enregistre chacune des modifications apportées aux champs de la société. Une société a donc une liste d'objets Historiques.

    Sous ma fiche d'edition j'ai un JTabbedPane composé de deux onglets : un Historique qui affiche une liste d'objets Historique, et un objet Groupe qui affiche une liste des sociétés appartenant à ce groupe (dont la société en cours d'edition fait partie).

    Tant que je n'avais pas ajouté l'onglet Groupe cela fonctionnait bien. C'est à dire que ma société était bien chargée ainsi que ses Historiques, ce qui prouve bien qu'une session est active à ce moment là et que mon objet Société y est bien attaché (en état persistant puisque j'ai pris soin de le ré-attacher à la session de la fenêtre d'edition avec la commande session.update()).

    Le problème survient quand je veux charger la liste des sociétés du groupe.
    Dans la fonction qui initialise mon affichage (et qui charge les données) je récupère le groupe auquel appartient la société.
    Ensuite je teste si le groupe récupéré est null (ce qui veut dire que la société n'appartient pas à un groupe) et s'il n'est pas nulle je charge sa liste de sociétés dans une JTable de façon tout à fait classique.
    C'est à ce moment là que l'erreur survient et la liste des sociétés n'est pas récupérées.

    Ce que je trouve étrange c'est qu'une session existe et est fonctionnelle à ce moment là et que je me retrouve avec un "No session or session was closed".

    Sachant que ma société est correctement liée à une session, comment se fait-il que le Groupe que je récupère via societe.getGroupe() ne le soit pas ?

    J'ai effectué un session.update(legroupe) pour l'attacher à la session et j'ai une erreur qui me dit qu'un objet avec la même clé primaire existe.
    Si j'effectue un session.merge(legroupe) il ne se passe rien et j'ai la même erreur.

    Je précise également que j'ouvre toutes mes sessions avec openSession() et que c'est moi qui les ferme explicitement.

    Je vous remercie d'avance pour l'aide que vous pourrez m'apporter

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Montre nous un peu de code, ouverture de session, utilisation, fermeture de session.

  3. #3
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut
    Je n'ai gardé que ce qui était significatif (à mon sens).

    En gros j'ai un champ static qui sert à stocker la société pour l'avoir sous la main et une variable de type Session pour stocker la session.

    Le code exécuté à l'affichage/dés-affichage du panel est dans les fonctions componentShown()/componentHidden().

    La fonction populateData charge les données de la société et rempli les composants de l'interface graphique.

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    public class SocietePanel extends javax.swing.JPanel{
    	//Données significatives
    	private static Societe societe;
    	private Session currentSession
    	private JXTable tHisto
     
     
    	private void initGUI() {
    		...
                    //JTable allant contenir respectivement l'historique des modifications et la liste des sociétés du groupe
    		tHisto = new JXTable();
                    tSocGroupe = new JXTable();
    		//Initialisation de l'interface graphique
    		this.addComponentListener(new ComponentListener() {
     
    		@Override
    		public void componentShown(ComponentEvent e) {
    			currentSession = HibernateUtil.getSessionFactory().openSession();
    			System.out.println("SocietePanel - Session Opened");
     
    			//Reattachement de la socieété
    			currentSession.update(societe);
    			try {						
    				populateData(societe);
    			} catch (Exception e1) {
    				// TODO Auto-generated catch block
    				e1.printStackTrace();
    			}
     
    			@Override
    			public void componentResized(ComponentEvent e) {
    			System.out.println(e);
     
     
     
    			@Override
    			public void componentMoved(ComponentEvent e) {
    				System.out.println(e);
     
    			}
     
    			@Override
    			public void componentHidden(ComponentEvent e) {
    				if(currentSession != null) {
    					currentSession.close();
    					System.out.println("SocietePanel - Session Closed");
    					societe = null;	
    				}
     
     
    			}
    		});
    	}
     
    	private void populateData(final Societe s) throws Exception {	
    		Runnable loadData = new Runnable() {			
    			@Override
    			public void run() {
    				try {					
     
    					initHist(s);
    					initGroupe(s);
    					societe = s;
    				} catch (Exception e1) {
    					// TODO Auto-generated catch block
    					e1.printStackTrace();
    				}												
    			}
    		};
    		Thread t = new Thread(loadData);
    		t.start();
     
    	}
     
     
    	public static void setSociete(Societe s) {
    		societe = s;
    	}
     
     
    	private void initHist(final Societe s) {
    		EventList<HistoriqueSociete> lstHist = GlazedLists.eventList(s.getHistorique());
    		String[] prop = {"champ", "oldValue", "newValue", "commiter", "dateModif"}; 
    		String[] col = {"Champ", "Ancienne valeur", "Nouvelle valeur", "Utilisateur", "Date de modification"};
    		TableFormat<HistoriqueSociete> tf = GlazedLists.tableFormat(HistoriqueSociete.class, prop, col);
     
    		EventTableModel<HistoriqueSociete> etm = new EventTableModel<HistoriqueSociete>(lstHist, tf);
    		tHisto.setModel(etm);
    	}
     
    	private void initGroupe(final Societe s) {
    		if(s.getGroupe() != null) {
    			Groupe grp = s.getGroupe();
     
    			//Ligne qui déclenche l'exception
    			EventList<Societe> lstSoc = GlazedLists.eventList(grp.getSocietes());
    			String[] prop = {"nom", "countryTel", "tel", "countryFax", "fax", "cp", "ville", "mail", "adresse1", "adresse2", "adresse3", "commercial", "secteur", "statut", "recommanded", "effectif", "porteurs", "groupe", "categorie", "solvabilite", "naf"}; 
    			String[] col = {"Nom", "Indic. Pays", "Telephone", "Indic. Pays", "Fax", "Code Postal", "Ville", "E-mail", "Adresse 1", "Adresse 2", "Adresse 3", "Commercial", "Secteur", "Statut", "Recommandé par", "Effectif", "Porteurs", "Groupe", "Categorie", "Solvabilité", "Code NAF"};
    			TableFormat<Societe> tf = GlazedLists.tableFormat(Societe.class, prop, col);
     
    			EventTableModel<Societe> etm = new EventTableModel<Societe>(lstSoc, tf);
    			tSocGroupe.setModel(etm);
     
    			esm = new EventSelectionModel<Societe>(lstSoc);
    			tSocGroupe.setSelectionModel(esm);
    		}
    	}
    }
    Et voici le bout de code qui appelle ce panel, il est situé dans un autre panel et intervient lors d'un double-clic sur un enregistrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public void mouseClicked(MouseEvent evt) {
    		if(evt.getClickCount() == 2) {
    			Societe s = esm.getSelected().get(0);
    			if(s != null) {							
    				try {
    					SocietePanel.setSociete(s);
    					DisplayManager.show("societe");								
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    DisplayManager est une simple classe qui me garde sous la main le JPanel et son CardLayout dans lequel doivent s'afficher mes autres panels.
    Lorsque la fonction DisplayManager.show() est appellée le code situé dans componentHidden() de ce second Panel s'exécute :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void componentHidden(ComponentEvent e) {
    		if(currentSession != null) {
    			currentSession.close();	
    			closingDisplay();
    			System.out.println("SocieteSearchPanel - Session Closed");
    		}					
    	}
    Dans ma console j'ai bien ceci qui s'affiche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SocieteSearchPanel - Session Closed
    SocietePanel - Session Opened
    Ce qui prouve que la première session est bien fermée et que la seconde s'ouvre correctement. La société ayant été chargée dans la première session je dois la réattacher à la nouvelle Session, c'est ce qui est fait dans la fonction componentShown() du second JPanel.

    J'espère que j'ai été assez clair, n'hésitez pas à demander plus d'infos

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Qu'as tu mis comme valeur pour la propriété hibernate.current_session_context_class de ton hibernate.cfg.xml.
    Comme tu utilises un autre thread il est possible que la valeur thread pose problème.

  5. #5
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut
    En effet j'ai laissé à "thread" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     <property name="current_session_context_class">thread</property>
    Mais ça n'a pas d'importance vu que je n'utilise pas getCurrentSession(), ou alors je me trompe ?

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Effectivement, tu n'utilises pas le getCurrentSession donc cela ne devrait pas poser de problème.

Discussions similaires

  1. Réponses: 0
    Dernier message: 30/11/2011, 21h58
  2. Savoir si une session est encore active
    Par jojo86 dans le forum Langage
    Réponses: 10
    Dernier message: 22/08/2011, 23h45
  3. Réponses: 5
    Dernier message: 28/04/2010, 10h33
  4. Réponses: 3
    Dernier message: 12/09/2007, 12h10
  5. Réponses: 2
    Dernier message: 14/02/2007, 11h34

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