Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JPA: загружать или не загружать связанные сущности, при использовании OneToMany 
:(
    Опции темы
LuMee
Дата 7.8.2007, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 117
Регистрация: 30.3.2007

Репутация: нет
Всего: 1



Много где видел похожие вопросы, но так и не нашел внятного ответа. 
Итак, пусть имеются две сущности, скажем, тема форума и сообщение в теме:
Код

@Entity
public class Topic
{
    ...
    @OneToMany(...)
    private Collection<Post> posts;
    ...
}

@Entity
public class Post
{
    ...
}

Вопросы таковы:
1. можно ли вытащить с помощью EntityManager'а объект Topic, не извлекая для него список Post'ов? А то, если уж говорить о форуме, то для извлечения списка топиков для отображения его на главной странице совершенно необязательно тащить еще и сообщения (так никакой памяти не хватит)
2. если удался п. 1, то как надежно проверить, что коллекция posts не проинициализирована? Она будет просто null, или там что похитрее?
3. опять же, если все нормально прошло с п.1, то как потом при необходимости все-таки проинициализировать эту коллекцию (тут уже догадки есть, но пока нет возможности проверить)?
По п.1, знаю, есть у аннотации OneToMany параметр fetchType, но, как я понял, установка ему значения FetchType.LAZY не гарантирует, что дочерние сущности не будут извлечены, ибо сервер приложений может данный параметр просто проигнорировать. Есть ли надежный способ убедить его лишние сущности не тащить, или остается только положиться на его умение следить за ресурсами?
PM MAIL   Вверх
Stampede
Дата 7.8.2007, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Коль скоро речь идет о веб приложении (форум), то я бы вообще не полагался на автоматический подгруз связанных сущностей. Дело в том, что в вебных интерфейсах практически для любых видов коллекций нужно предусматривать постраничный просмотр. И это требование делает объявления вида @OneToMany практически бесполезными.



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
LuMee
Дата 8.8.2007, 07:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 117
Регистрация: 30.3.2007

Репутация: нет
Всего: 1



Мда, неудачно я видимо пример привел... А если рассматривать более общую ситуацию, нежели сущности для отображения на странице? Пусть, скажем, это будут некие сущности, описывающие какие-то внутренности системы или еще чего. У меня пока складывается впечатление, что самым простым и надежным способом добиться желаемого результата будет вообще забыть про OneToMany и вытаскивать все данные самостоятельно, однако это уже не так красиво.
PM MAIL   Вверх
ecologist
Дата 8.8.2007, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 452
Регистрация: 28.2.2007

Репутация: 5
Всего: 9



По моему мнению EJB использует идеологию Hibernate, а там LAZY будет нормально работать только в рамках транзакции. Отсюда у меня вывод:
Использовать "ленивые" коллекции можно и нужно, но каждый раз это должно продумываться и тестироваться.
PM MAIL   Вверх
LuMee
Дата 8.8.2007, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 117
Регистрация: 30.3.2007

Репутация: нет
Всего: 1



Оно понятно, что можно и нужно (не зря же люди их делали smile), вопрос в том, как обеспечить желаемое их поведение.

По моему мнению EJB использует идеологию Hibernate, а там LAZY будет нормально работать только в рамках транзакции
Вот с этого места можно немного поподробнее? А то с Hibernate лично дел не имел.
PM MAIL   Вверх
Maverick
Дата 9.8.2007, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



Как все-таки проинициализировать коллекцию... ? smile 


--------------------
smile
PM ICQ GTalk   Вверх
AntonSaburov
Дата 9.8.2007, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 8
Всего: 118



Код

        try {
            Session session = template.getSessionFactory().getCurrentSession();
            Agency result = (Agency) session.get(Agency.class, new Integer(agencyRowId));
            if(result!=null) {
                Hibernate.initialize(result.getTerminal());
                Hibernate.initialize(result.getMnemonics());
            }
            return result;
        } catch (HibernateException e) {
            throw new DataAccessException(e);
        }



Строчку с session - там получение сессии Hibernate. А дальше - первый шаг - получение объекта Agency. И после инициализация двух коллекций - терминалы и мнемоники. Ну это просто кусок выдраный из кода.

Вот что важно - Hibernate.initialize(...)
PM MAIL WWW ICQ   Вверх
Maverick
Дата 10.8.2007, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



А в Ejb3?

Добавлено через 2 минуты и 36 секунд
у меня вот такую хрень выдает
Код

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: bnkMain.Agent.declarations, no session or session was closed


если прописать fetchtype =EAGER, то возникает другая....

ну не хочу я пока использовать эту ленивую загрузку, чего она лезет... 


--------------------
smile
PM ICQ GTalk   Вверх
AntonSaburov
Дата 10.8.2007, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 8
Всего: 118



Видимо ты пытаешься инициализировать коллекцию уже за границей открытия сессии.

По сути ты можешь вытащить коллекцию ТОЛЬКО пока сессия еще открыта. Как только ты ее закрываешь, то все.

Образно - открыли дверку (сессию) - и ты можешь таскать данные, записывать и прочая. Как только дверка закрыта (сессия) - все. Тебе так и написали.
PM MAIL WWW ICQ   Вверх
Maverick
Дата 13.8.2007, 08:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



Дело в том, что я не использую прямо сессии и ленивую загрузку... я вообще не хочу это делать прямо - не настолько опытен еще.... а все равно вылазит  всякое...

Добавлено через 1 минуту и 45 секунд
Код

Session session = template.getSessionFactory().getCurrentSession();


если можно - чуть подробнее об этой строке.... что такое template? Это экземпляр чего?

Добавлено через 2 минуты и 13 секунд
И в каком методе сидят эти строчки?


--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 13.8.2007, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



Ставлю fetch = EAGER вот такая штука вылазит

Код

Caused by: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags




--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 13.8.2007, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



нельзя ли расписать примерчик... очень прошу - кто уже разобрался...

есть два entity со связь @OneToMany, даже три - вложенных... вот так примерно...

Код


//-*-*-*-*-*-*-*-*
@Entity
 // экономический агент
public class Agent implements Serializable {

    @OneToMany(mappedBy = "agent", fetch = FetchType.EAGER, cascade =CascadeType.ALL)
    private List<Declaration>  declarations = new ArrayList<Declaration>();

//-*-*-*-*-*-*-*-*
@Entity 
// таможенная декларация
public class Declaration implements Serializable {

    @ManyToOne
    private Agent agent;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    /** Номер декларации */
    private String issue;
    /** Признак завершения оформления*/
    private Boolean clear;
    
    @OneToMany(mappedBy = "declaration")
    private List<Payment> payments = new ArrayList<Payment>();

//-*-*-*-*-*-*-*-*
@Entity
// таможенные платеж дл декларации
public class Payment   implements Serializable{
 
    @ManyToOne
    private Declaration declaration;
       


как с ними обращаться, чтобы все коллекции отвечали нормально? где-какие сессии открывать? как их проинициалировать? я пытаюсь и так и этак... пол инета перерыл...

Добавлено через 49 секунд
хотя бы направьте - в каком направлении рыть...  заранее благодарен... 


--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 13.8.2007, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



В последнее время -у меня стойкое мнение, что я один русскоязычный на планете занимаюсь EJB3... 
проблема описана ... но ее решение в данном случае мне не подходит - там чистый Hibernate... да оно и не работает нормально  под EJB3...  


--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 13.8.2007, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: 2
Всего: 10



Переключил проект на TopLink - все заработало сразу и нормально...  smile  как это называется? Hibernate глючит?


--------------------
smile
PM ICQ GTalk   Вверх
AntonSaburov
Дата 13.8.2007, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 8
Всего: 118



Цитата(Maverick @  13.8.2007,  08:45 Найти цитируемый пост)
если можно - чуть подробнее об этой строке.... что такое template? Это экземпляр чего?

Эту строчку как раз не надо рассматривать - это наш внутренний класс - но там вообщем надо получить сессию. 
Вот из той же доки по Hibernate

Код

package util;
import org.hibernate.*;
import org.hibernate.cfg.*;
public class HibernateUtil 
{
  private static final SessionFactory sessionFactory;
  static {
    try {
      // Create the SessionFactory from hibernate.cfg.xml
      sessionFactory = new Configuration().configure().buildSessionFactory();
    } catch (Throwable ex) {
      // Make sure you log the exception, as it might be swallowed
      System.err.println("Initial SessionFactory creation failed." + ex);
      throw new ExceptionInInitializerError(ex);
    }
  }
  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }
}

Код

Session session = HibernateUtil.getSessionFactory().getCurrentSession();



PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.1184 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.