Будьте в спящем режиме JPA - отношения ManyToOne, не заполненные

Я в настоящее время перемещаю (рабочее) приложение от использования EclipseLink для Спящего режима JPA, главным образом это пошло вполне гладко, но я нахожу одну вещь, которую я не могу объяснить и также не могу думать ни о каких хороших критериях поиска!

В основном у меня есть четыре объекта со связями "один ко многим", формирующими цепочку:

EntityA имеет список EntityB, каждый из которых имеет список EntityC, каждый из которых имеют список EntityD

у каждого из тех затем есть many-one отношения, идущие другим путем, таким образом:

EntityD имеет EntityC, который имеет EntityB, который имеет EntityA.

Это (в большой степени уменьшено для ясности):

@Entity
public class EntityA {
  @OneToMany (cascade = CascadeType.All, mappedBy = "entityA")
  private List<EntityB> entityBList;
  ...
}

@Entity
public class EntityB {
  @OneToMany (cascade = CascadeType.All, mappedBy = "entityB")
  private List<EntityC> entityCList;

  @JoinColumn (name = "ENTITY_A", referencedColumnName = "ENTITY_A_ID")
  @ManyToOne (cascade = CascadeType.PERSIST, optional = false)
  private EntityA entityA;
}

@Entity
public class EntityC {
  @OneToMany (cascade = CascadeType.ALL, mappedBy = "entityC")
  private List<EntityD> entityDList;

  @JoinColumn (name = "ENTITY_B", referencedColumnName = "ENTITY_B_ID")
  @ManyToOne (cascade = CascadeType.PERSIST, optional = false)
  private EntityB entityB;
}

@Entity
public class EntityD {
  @JoinColumn (name = "ENTITY_C", referencedColumnName = "ENTITY_C_ID")
  @ManyToOne (cascade = CascadeType.PERSIST, optional = false)
  private EntityC entityC;
}

Я получаю EntityA от базы данных (ищущий его ее первичным ключом) и таким образом получаю приятно заполненный экземпляр EntityA с PersistentBag для моего List<EntityB>. Я вижу, что ленивая загрузка происходит, когда я разыменовываю это List<EntityB>, и то же, повторенное для получения EntityCs от EntityB.

На данном этапе все - как я ожидаю, у меня есть EntityA, B и C все полностью заполненные со значениями от базы данных, но затем я пытаюсь получить свой EntityD от EntityC, и найти, что это является пустым.

Мой менеджер по объекту все еще открыт и активен в этой точке, и даже если я смотрю на нее в отладчике сразу после получения EntityA, я могу идти через отношения, до EntityC, и снова рассматривать 'entityDList' как пустой указатель.

Единственное решение, которое я нашел до сих пор, состоит в том, чтобы использовать:

EntityManager.refresh(entityC);

который заполняет все его элементы включая лениво загруженный PersistentBag для entityDList.

Так, мое предположение, это В спящем режиме, только заполняет ссылки 2 уровня глубоко (или 3, в зависимости от того, как Вы рассчитываете), и сдающийся после этого, хотя я действительно не понимаю, почему это было бы. Это имеет смысл кому-либо?

Есть ли какое-либо решение кроме .refresh? Некоторая конфигурация или значение аннотации, которое сделает, в спящем режиме, заполняют ссылки полностью вниз?

6
задан DaveyDaveDave 29 June 2010 в 10:56
поделиться

3 ответа

Спасибо за предложения от людей, которые, вероятно, актуальны, но не помогли в моем конкретном случае.

Если вы читаете это и сталкиваетесь с той же проблемой, возможно, стоит попробовать предложение max_fetch_depth , но по какой-то причине у меня это не сработало (мне бы хотелось узнать, почему?) .

Аналогичным образом, если ваши @OneToMany являются наборами, а не списками, выполнение активной выборки или левого соединения, как предлагает Альберт, может работать, но, очевидно, Hibernate позволяет вам иметь максимум 1 Список, который охотно выбирается, если вам нужно больше, ваши коллекции должны быть наборами. Я не пробовал, но подозреваю, что это могло решить проблему.

Если у кого-то нет лучшего предложения, я буду продолжать вызывать обновление, что в любом случае, вероятно, имеет больше смысла для моего приложения.

3
ответ дан 17 December 2019 в 04:41
поделиться

Это действительно смешно. Один из способов обойти это - запросить объект A с левым соединением для -> B-> C-> D, что также будет быстрее, если вы все равно собираетесь перейти к объекту D. Было бы что-то вроде этого.

"from A left join fetch B left join fetch C left join fetch D"

Вы тоже пытались установить отношения с C-> D нетерпеливо? Любопытно, что будет потом ...

1
ответ дан 17 December 2019 в 04:41
поделиться

В документации по спящему режиму сказано, что вы можете установить его с помощью свойства hibernate.max_fetch_depth. Значение по умолчанию - 3. Его можно найти в «Справочной документации по Hibernate» на стр. 47.

1
ответ дан 17 December 2019 в 04:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: