Note that there are some explanatory texts on larger screens.

plurals
  1. POI can't access a list after query in a one-to-many relation with Hibernate and Criteria
    text
    copied!<p>I have a problem with Hibernate, one-to-many associations and lists. In my model, I have countries and, for each country, I have multiple information describing a structure for addresses in that country. I want to access the list of these elements.</p> <p>This my class Country :</p> <pre><code>public class Country { private Long id; private String name; private List&lt;AddressElement&gt; addressElementList = null; ... } </code></pre> <p>My class AddressElement:</p> <pre><code>public class AddressElement { private Long id; private int pos; private int line; private String name; private String mask; ... } </code></pre> <p>And my mappings :</p> <pre><code>&lt;hibernate-mapping package="org.devtutos.tuto5.domaine"&gt; &lt;class name="Country" table="tuto.COUNTRY"&gt; &lt;id name="id" type="java.lang.Long" column="COUNTRY_ID" unsaved-value="null"&gt; &lt;generator class="native"&gt; &lt;param name="sequence"&gt;tuto.SEQ_COUNTRY&lt;/param&gt; &lt;/generator&gt; &lt;/id&gt; &lt;natural-id mutable="true"&gt; &lt;property name="name" column="COUNTRY_NAME" type="java.lang.String"/&gt; &lt;/natural-id&gt; &lt;list name="addressElementList" table="tuto.ADDRESS_ELEMENT" lazy="false"&gt; &lt;key foreign-key="country_address_element_fk"&gt; &lt;column name="COUNTRY_ID" not-null="true"/&gt; &lt;/key&gt; &lt;list-index&gt; &lt;column name="ADDRESS_ELEMENT_POS" not-null="true" /&gt; &lt;/list-index&gt; &lt;one-to-many class="AddressElement"/&gt; &lt;/list&gt; &lt;/class&gt; &lt;/hibernate-mapping&gt; &lt;hibernate-mapping package="org.devtutos.tuto5.domaine"&gt; &lt;class name="AddressElement" table="tuto.ADDRESS_ELEMENT"&gt; &lt;id name="id" type="java.lang.Long" column="ADDRESS_ELEMENT_ID" unsaved-value="null"&gt; &lt;generator class="native"&gt; &lt;param name="sequence"&gt;tuto.SEQ_ADDRESS_ELEMENT&lt;/param&gt; &lt;/generator&gt; &lt;/id&gt; &lt;property name="line" column="ADDRESS_ELEMENT_LINE" not-null="true" type="java.lang.Integer" /&gt; &lt;property name="name" column="ADDRESS_ELEMENT_NAME" not-null="true" type="java.lang.String" /&gt; &lt;property name="mask" column="ADDRESS_ELEMENT_TYPE_MASK" not-null="true" type="java.lang.String" /&gt; &lt;property name="pos" column="ADDRESS_ELEMENT_POS" not-null="true" type="java.lang.Integer" /&gt; &lt;/class&gt; &lt;/hibernate-mapping&gt; </code></pre> <p>This my code:</p> <pre><code>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())); } } </code></pre> <p>This is my log :</p> <pre><code>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' -&gt; '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) </code></pre> <p>I can't access the information of address elements from a country. I tried several things: I turned on lazy mode and specified a fetch mode with JOIN but it doesn't work. The most surprising is the list is populated (there are 4 elements) and the following code runs well (So, the information is in the database, setters and getters work):</p> <pre><code>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())); } </code></pre> <p>These is the result of this code:</p> <pre><code>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 </code></pre> <p>I noticed in my first execution that the size of my list is wrong (4 instead of 3). In my example, the value of <code>countryName</code> is "FRANCE". This is the content of my tables:</p> <p>COUNTRY:</p> <pre><code>COUNTRY_ID CONTRY_NAME 1 "FRANCE" 2 "HYPERION" 3 "ATLANTIS" </code></pre> <p>ADDRESS_ELEMENT:</p> <pre><code>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 </code></pre> <p>What am I doing wrong? I don't understand why <code>elem</code> is null in the first execution. Can somebody help me?</p> <p>Thanks in advance.</p> <p>Have a happy new year. ;-)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload