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 :

Problème de récupération d'une liste avec Criteria et association one-to-many


Sujet :

Hibernate Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Problème de récupération d'une liste avec Criteria et association one-to-many
    Bonjour,

    J'ai un problème avec Hibernate, une association one-to-many et les listes associées. Dans mon modèle, j'ai une classe Country et, pour chaque instance de Country, j'ai plusieurs informations qui décrivent une structure pour les adresses associées à cette instance.

    Voici ma classe Country :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        public class Country {
     
        private Long id;
        private String name;
        private List<AddressElement> addressElementList = null;
        ...
        }
    ma classe AddressElement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        public class AddressElement {
     
        private Long id;
        private int pos;
        private int line;
        private String name;
        private String mask;
        ...
        }
    et le mapping hibernate :

    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
        <hibernate-mapping  package="org.devtutos.tuto5.domaine">								
        <class  name="Country" table="tuto.COUNTRY" >
    		<id name="id" type="java.lang.Long" column="COUNTRY_ID" unsaved-value="null">		
    			<generator class="native">	
    				<param name="sequence">tuto.SEQ_COUNTRY</param>
    			</generator>
            </id>
            <natural-id mutable="true">
           		<property 	name="name"  column="COUNTRY_NAME" type="java.lang.String"/>      
            </natural-id>
        	<list name="addressElementList" table="tuto.ADDRESS_ELEMENT" lazy="false">
              <key  foreign-key="country_address_element_fk">
              	<column name="COUNTRY_ID" not-null="true"/>	
              </key>
              <list-index>
                   <column name="ADDRESS_ELEMENT_POS" not-null="true" />
              </list-index>
              <one-to-many class="AddressElement"/>   
        	</list>
        </class>
        </hibernate-mapping>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        <hibernate-mapping  package="org.devtutos.tuto5.domaine">								
        <class  name="AddressElement" table="tuto.ADDRESS_ELEMENT" >
    		<id name="id" type="java.lang.Long" column="ADDRESS_ELEMENT_ID" unsaved-value="null">		
              <generator class="native">	
              		<param name="sequence">tuto.SEQ_ADDRESS_ELEMENT</param>
              </generator>
            </id>
            <property name="line" column="ADDRESS_ELEMENT_LINE" not-null="true" type="java.lang.Integer" />
            <property name="name" column="ADDRESS_ELEMENT_NAME" not-null="true" type="java.lang.String" />
            <property name="mask" column="ADDRESS_ELEMENT_TYPE_MASK" not-null="true" type="java.lang.String" />
            <property name="pos" column="ADDRESS_ELEMENT_POS" not-null="true" type="java.lang.Integer" />
        </class>
        </hibernate-mapping>
    Voici mon code :

    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
        criteria = getSessionFactory().getCurrentSession().createCriteria(Country.class);
        criteria.add(Restrictions.eq("name", countryName));
        criteria.setFetchMode("addressElementList",FetchMode.JOIN);
     
        Country country = (Country) criteria.list().get(0);
     
        if (country == null) {
     
        	logger.log(Level.INFO, "ERREUR DE COHERENCE INTERNE : Pays '".concat(countryName).concat("'non trouvé:"));
        }
        else {
        	logger.log(Level.INFO, "Pays trouvé.");
        	logger.log(Level.INFO, "Nom du Pays :".concat(country.getName()));
        	logger.log(Level.INFO, "Code du Pays :".concat(String.valueOf(country.getId())));
        	liste = country.getAddressElementList();
        	logger.log(Level.INFO, "Taille de la liste des éléments d'adresse :".concat(String.valueOf(liste.size())));
        	for (AddressElement elem : liste){
        		if (elem == null) {logger.log(Level.INFO, "L'élément d'adresse est null.");}
        			logger.log(Level.INFO, "Element de la liste : ID = ".concat(String.valueOf(elem.getId())));    **** Line of the error
        			logger.log(Level.INFO, "Element de la liste : POS = ".concat(String.valueOf(elem.getPos())));
        			logger.log(Level.INFO, "Element de la liste : NOM = ".concat(elem.getName()));
        		}
        	}
        }
    Et voici ma log :

    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
        Hibernate: 
        select 
        this_.COUNTRY_ID as COUNTRY1_2_1_, 
        this_.COUNTRY_NAME as COUNTRY2_2_1_, 
        addressele2_.COUNTRY_ID as COUNTRY6_2_3_, 
        addressele2_.ADDRESS_ELEMENT_ID as ADDRESS1_3_, 
        addressele2_.ADDRESS_ELEMENT_POS as ADDRESS5_3_, 
        addressele2_.ADDRESS_ELEMENT_ID as ADDRESS1_0_0_, 
        addressele2_.ADDRESS_ELEMENT_LINE as ADDRESS2_0_0_, 
        addressele2_.ADDRESS_ELEMENT_NAME as ADDRESS3_0_0_, 
        addressele2_.ADDRESS_ELEMENT_TYPE_MASK as ADDRESS4_0_0_, 
        addressele2_.ADDRESS_ELEMENT_POS as ADDRESS5_0_0_ 
        from 
        tuto.COUNTRY this_ left outer join tuto.ADDRESS_ELEMENT addressele2_ 
        on this_.COUNTRY_ID=addressele2_.COUNTRY_ID 
        where 
        this_.COUNTRY_NAME=?
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Pays trouvé.
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Nom du Pays :FRANCE
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Code du Pays :1
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Taille de la liste des éléments d'adresse :4
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: L'élément d'adresse est null.
        27 déc. 2012 16:19:09 org.apache.catalina.core.StandardWrapperValve invoke
        GRAVE: Servlet.service() for servlet [tuto5] in context with path [/tuto-5] threw exception [Request processing failed; nested exception is org.springframework.webflow.execution.ActionExecutionException: Exception thrown executing [AnnotatedAction@3f610944 targetAction org.devtutos.tuto5.mvc.webflow.action.receptionAction@4dc6bbd3, attributes = map['method' -> 'enregistrerLUtilisateur']] in state 'enregistrerLUtilisateur' of flow 'reception' -- action execution attributes were 'map[[empty]]'] with root cause
        java.lang.NullPointerException
        at org.devtutos.tuto5.dao.CountryHibernate.getCountryByName(CountryHibernate.java:103)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
        ...
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
    Je ne peux pas accéder aux informations des éléments d'adresse pour mon instance de Country. J'ai essayé plusieurs choses : J'ai positionné le "lazy mode" à "true" et spécifié le "fetch mode" à "JOIN" mais cela ne marche pas. Le plus surprenant est que la liste est alimentée ( Il y a quatre éléments ) et le code suivant fonctionne correctement (Ainsi, les informations dans la base de données et les accesseurs sont corrects ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        logger.log(Level.INFO, "Lecture de tous les éléments d'adresse.");
        criteria = getSessionFactory().getCurrentSession().createCriteria(AddressElement.class);
        liste = criteria.list();
        logger.log(Level.INFO, "Taille de la liste des éléments d'adresse : ".concat(String.valueOf(liste.size())));
        for (AddressElement elem : liste){
        	if (elem == null) {logger.log(Level.INFO, "L'élément d'adresse est null.");}
        	logger.log(Level.INFO, "Element de la liste : ID = ".concat(String.valueOf(elem.getId())));
        	logger.log(Level.INFO, "Element de la liste : POS = ".concat(String.valueOf(elem.getPos())));
        	logger.log(Level.INFO, "Element de la liste : NOM = ".concat(elem.getName()));
        }
    Voici le résultat de ce code :

    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
        INFO: Lecture de tous les éléments d'adresse.
        Hibernate: select this_.ADDRESS_ELEMENT_ID as ADDRESS1_0_0_, this_.ADDRESS_ELEMENT_LINE as ADDRESS2_0_0_, this_.ADDRESS_ELEMENT_NAME as ADDRESS3_0_0_, this_.ADDRESS_ELEMENT_TYPE_MASK as ADDRESS4_0_0_, this_.ADDRESS_ELEMENT_POS as ADDRESS5_0_0_ from tuto.ADDRESS_ELEMENT this_
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Taille de la liste des éléments d'adresse : 6
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 1
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 1
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = Code Postal
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 2
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 2
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = Ville
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 3
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 3
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = Batiment
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 4
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 1
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = District
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 5
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 2
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = Zone
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : ID = 6
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : POS = 1
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
        INFO: Element de la liste : NOM = City
        27 déc. 2012 16:19:09 org.devtutos.tuto5.dao.CountryHibernate getCountryByName
    J'ai remarqué dans la première exécution que la taille de liste n'est pas bonne ( 4 au lieu de 3 ). Dans mon exemple, la valeur de "countryName" est "FRANCE". Voici le contenu de mes tables pour le test :

    COUNTRY :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        COUNTRY_ID		CONTRY_NAME 
        1			"FRANCE"
        2			"HYPERION"
        3			"ATLANTIS"
    ADDRESS_ELEMENT :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        ADDRESS_ELEMENT_ID		COUNTRY_ID		ADDRESS_ELEMENT_POS    	ADDRESS_ELEMENT_NAME    ADDRESS_ELEMENT_MASK	       ADDRESS_ELEMENT_LINE
        1				1			1		        "Code Postal"           "\d{5}"				1
        2				1			2		        "Ville"			"[A-Z\-]{1,50}"			1
        3				1			3		        "Batiment"		"[A-F]"				1
        4				2			1		        "District"		"[A-Z]{1,20}"			1 
        5				2			2		        "Zone"		        "[A-5]{1,5}"			2
        6				3			1		        "City"			"[A-Z]{1,9}"			1
    Qu'est-ce que je fais de mal ? Je ne comprends pas pourquoi "elem" est null dans la première exécution. J'ai besoin d'aide.

    Je vous remercie par avance.

    Bonne année à tous. ;-)

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Transports

    Informations forums :
    Inscription : Janvier 2013
    Messages : 21
    Points : 25
    Points
    25
    Par défaut
    Bonjour

    Il y a effectivement une incohérence entre la taille attendue de la liste des éléments d'adresse et la taille retournée.
    Dans ton code, tu affiche un message d'erreur si l'élément est null, mais malgré ceci, tu poursuis ton exploration de l'élément. Celui ci étant nul, un appel à l'une de ses méthodes (elem.getId()) renvoie une NPE. Il te manque sans doute un else après ton if de manière à ne pas executer le code qui va planter.

    Ceci dit, ça ne résoud pas le problème sur le fond. ça ne fait que le contourner

    Sinon as tu essayé de créer un sous-critère à partir de ton critère

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        criteria = getSessionFactory().getCurrentSession().createCriteria(Country.class);
        criteria.add(Restrictions.eq("name", countryName));
        criteria.createCriteria("addressElementList", CriteriaSpecification.LEFT_JOIN);
    On utilise ce mode de fonctionnement dans nos applis.

Discussions similaires

  1. problème de récupération d'une liste d'objet au niveau des DAO
    Par yness dans le forum Persistance des données
    Réponses: 1
    Dernier message: 25/04/2011, 19h57
  2. Réponses: 0
    Dernier message: 18/05/2009, 18h20
  3. récupération d'une List<> avec Cairngorm
    Par ziad.shady dans le forum MXML
    Réponses: 0
    Dernier message: 06/07/2008, 22h19
  4. Réponses: 0
    Dernier message: 26/05/2008, 16h41
  5. Problème d'affiche d'une list avec c:forEach
    Par lili2704 dans le forum Struts 1
    Réponses: 2
    Dernier message: 19/03/2007, 17h49

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