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 :
ma classe AddressElement :
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; ... }
et le mapping hibernate :
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; ... }
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>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 <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>
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 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())); } } }
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
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)
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 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())); }
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 :
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
COUNTRY :
ADDRESS_ELEMENT :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 COUNTRY_ID CONTRY_NAME 1 "FRANCE" 2 "HYPERION" 3 "ATLANTIS"
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.
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
Je vous remercie par avance.
Bonne année à tous. ;-)
Partager