Я не могу получить доступ к списку после запроса в отношении «один ко многим» с Hibernate и Criteria

У меня проблема с Hibernate, ассоциациями «один ко многим» и списками. В моей модели у меня есть страны, и для каждой страны у меня есть много информации, описывающей структуру адресов в этой стране. Я хочу получить доступ к списку этих элементов.

Это мой класс Страна:

public class Country {
  private Long id;
  private String name;
  private List addressElementList = null;
  ...
}

Мой класс AddressElement:

public class AddressElement {
  private Long id;
  private int pos;
  private int line;
  private String name;
  private String mask;
  ...
}

И мои сопоставления:


  
    
      
        tuto.SEQ_COUNTRY
      
    
    
      
    
    
      
        
      
      
        
      
      
    
  


  
    
      
        tuto.SEQ_ADDRESS_ELEMENT
      
    
    
    
    
    
  

Этот мой код:

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()));
  }
}

Это мой журнал:

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 [[email protected] targetAction [email protected], 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)

Я не могу получить доступ к информации о элементах адреса из страны. Я пробовал несколько вещей: я включил ленивый режим и задал режим выборки с помощью JOIN, но он не работает. Самое удивительное, что список заполнен (есть 4 элемента), и следующий код работает хорошо (Итак, информация находится в базе данных, сеттерах и геттерах):

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()));
}

Это результат этого кода:

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

В моем первом исполнении я заметил, что размер моего списка неверен (4 вместо 3). В моем примере значением countryName является «ФРАНЦИЯ». Это содержимое моих таблиц:

СТРАНА:

COUNTRY_ID      CONTRY_NAME 
1                    "FRANCE"
2                    "HYPERION"
3                    "ATLANTIS"

ADDRESS_ELEMENT:

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

Что я делаю не так? Я не понимаю, почему elem имеет значение null в первом выполнении. Может кто-нибудь мне помочь?

Заранее спасибо.

Счастливого Нового года. ;-)

0
nl ja de
Покажите нам полный код страны.
добавлено автор JB Nizet, источник
Спасибо за вашу помощь! Это полный код для субъекта страны. Есть только геттеры и сеттеры. hashCode() и equals (Object obj) были автоматически Eclipse.
добавлено автор Pascal, источник

2 ответы

Ваш список индексируется столбцом ADDRESS_ELEMENT_POS . Поэтому, если Hibernate загружает весь список адресов для страны 1 , он установит адрес 1 в индекс 1 (поскольку это значение ADDRESS_ELEMENT_POS для этого адреса), адрес 2 по индексу 2, а addres 3 - по индексу 3. И поскольку адрес с кодом отсутствует, индекс 0 список будет пустым.

Вычитайте 1 в значения вашего ADDRESS_ELEMENT_POS в базе данных или добавьте следующий атрибут в элемент конфигурации list-index : base = "1" . См. http://docs.jboss.org/hibernate /core/3.6/reference/en-US/html_single/#d0e10924 .

0
добавлено
Он работает очень хорошо !!!!
добавлено автор Pascal, источник

Спасибо за вашу помощь!

Это полный код для субъекта страны. Есть только геттеры и сеттеры. hashCode() и equals (Object obj) были автоматически Eclipse.

package org.devtutos.tuto5.domaine;

import java.util.ArrayList;
import java.util.List;

public class Country {

    private Long id;
    private String name;
    private List addressElementList = null;

    public Country(){}

    public Long getId() {
        return id;
    }  

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   

    public void addAddressElement( int pos, int line, String name, String mask){
        addressElementList.add(new AddressElement(pos,line,name,mask));
    }

    public List getAddressElementList() {
        return addressElementList;
    }

    public void setAddressElementList(List addressElementList) {
        this.addressElementList = addressElementList;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
             return false;
        if (getClass() != obj.getClass())
            return false;
        Country other = (Country) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
}

Я не знаю, где проблема. Еще раз спасибо...

0
добавлено
Не добавляйте это как ответ. Это не одно. Нажмите ссылку «Изменить» в нижней части вашего вопроса и добавьте код в свой вопрос.
добавлено автор JB Nizet, источник
Верстка сайтов HTML/CSS/JS/PHP
Верстка сайтов HTML/CSS/JS/PHP
3 439 участник(ов)

Правила группы: напишите !rules в чате. Группа Вк: vk.com/web_structure Freelancer: @web_fl Веб Дизайн: @dev_design Маркетолог: @topmarkening Автор: @M_Boroda

CSS — русскоговорящее сообщество
CSS — русскоговорящее сообщество
1 502 участник(ов)

Сообщество любителей CSS Возникли проблемы с CSS? – пиши сюда, обсудим и предложим самое лучшее решение Работа: @css_ru_jobs Правила: https://teletype.in/@css_ru/r1EWtQ2w7 Приходите в наши чаты @javascript_ru и @frontend_ru Флуд: @css_flood

Чат — Типичный Верстальщик
Чат — Типичный Верстальщик
1 080 участник(ов)

Основной канал: @tpverstak Обратная связь: @annblok Все ссылки на соц.сети проекта: http://taplink.cc/tpverstak ПРАВИЛА ЧАТА — https://teletype.in/@annblok/BygPgC3E7

Веб-Технологи: UI/UX, Вёрстка, Фронтенд
Веб-Технологи: UI/UX, Вёрстка, Фронтенд
167 участник(ов)

Всё про веб-дизайн и вёрстку. А также: HTML, CSS, флекс и бутстрапы, шаблонизаторы, препроцессоры, методологии, аглифаеры, улучшаторы и обфускаторы. Обсуждаем темы юзабилити, устраиваем А/В тесты лендингов, и проводим аудит.

DTP :: @DTPublish
DTP :: @DTPublish
147 участник(ов)

Обсуждаемые темы: полиграфия, препресс, верстка, дизайн, иллюстрации, скрипты, плагины. Канал - @DTPublishing

css_jobs
css_jobs
26 участник(ов)

Чат для вопросов по css и html: @css_ru Флуд: @css_flood Канал с вакансиями и резюме: @css_jobs_feed

css_флуд
css_флуд
10 участник(ов)