Hibernate не может одновременно получать несколько пакетов - PullRequest
405 голосов
/ 02 декабря 2010

Hibernate выдает это исключение при создании SessionFactory:

org.hibernate.loader.MultipleBagFetchException: невозможно одновременно получить несколько пакетов

Это мой тестовый пример:

Parent.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 // @IndexColumn(name="INDEX_COL") if I had this the problem solve but I retrieve more children than I have, one child is null.
 private List<Child> children;

}

Child.java

@Entity
public Child {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private Parent parent;

}

Как насчет этой проблемы? Что я могу сделать?


EDIT

ОК, у меня проблема в том, что внутри моего родителя находится другая «родительская» сущность, мое реальное поведение таково:

Parent.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private AntoherParent anotherParent;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<Child> children;

}

AnotherParent.java

@Entity
public AntoherParent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<AnotherChild> anotherChildren;

}

Hibernate не любит две коллекции с FetchType.EAGER, но это похоже на ошибку, я не делаю необычных вещей ...

Удаление FetchType.EAGER из Parent или AnotherParent решает проблему, но мне это нужно, поэтому реальным решением является использование @LazyCollection(LazyCollectionOption.FALSE) вместо FetchType (благодаря Божо для раствор).

Ответы [ 12 ]

485 голосов
/ 02 декабря 2010

Я думаю, что более новая версия hibernate (поддерживающая JPA 2.0) должна справиться с этим.Но в противном случае вы можете обойти это, пометив поля коллекции с помощью:

@LazyCollection(LazyCollectionOption.FALSE)

Не забудьте удалить атрибут fetchType из аннотации @*ToMany.

Но обратите внимание, что в большинстве случаевSet<Child> более подходит, чем List<Child>, поэтому, если вам действительно не нужен List - переходите к Set

270 голосов
/ 03 мая 2011

Просто измените тип List на тип Set.

115 голосов
/ 29 ноября 2011

Добавьте аннотацию @Fetch, относящуюся к Hibernate, к своему коду:

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;

Это должно исправить проблему, связанную с ошибкой Hibernate HHH-1718

24 голосов
/ 27 февраля 2014

Попробовав каждую опцию, описанную в этом и других постах, я пришел к выводу, что исправление является следующим.

В каждом XToMany месте @ XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) и промежуточно после

@Fetch(value = FetchMode.SUBSELECT)

Это сработало для меня

19 голосов
/ 05 сентября 2014

Чтобы исправить это, просто возьмите Set вместо List для вашего вложенного объекта.

@OneToMany
Set<Your_object> objectList;

и не забудьте использовать fetch=FetchType.EAGER

, это будет работать.

В Hibernate есть еще один концепт CollectionId, если вы хотите придерживаться только списка.

11 голосов
/ 11 января 2013

Я нашел хороший пост в блоге о поведении Hibernate в таких сопоставлениях объектов: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

6 голосов
/ 25 апреля 2017

Вы можете сохранить списки стендов EAGER в JPA и добавить хотя бы к одному из них аннотацию JPA @ OrderColumn (очевидно, с именем поля, которое нужно упорядочить). Нет необходимости в специальных спящих аннотациях. Но имейте в виду, что это может создать пустые элементы в списке, если выбранное поле не имеет значений, начинающихся с 0

 [...]
 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 @OrderColumn(name="orderIndex")
 private List<Child> children;
 [...]

в Children, тогда вы должны добавить поле orderIndex

3 голосов
/ 27 июня 2018

Причина, по которой вы получаете это исключение, заключается в том, что Hibernate в конечном итоге сделает декартово произведение, которое ухудшает производительность.

Теперь, хотя вы могли бы «исправить» проблему, используя Set вместо List, вы не должны этого делать, потому что декартово произведение все равно будет включено в базовые операторы SQL.

Вам лучше переключиться с FetchType.EAGER на Fetchype.LAZY, поскольку активная выборка - ужасная идея , которая может привести к критическим проблемам с производительностью приложения .

Если вам нужно выбрать дочерние объекты по многоуровневой иерархии, лучше выбрать от самого внутреннего потомка до родителей , как описано в этой статье .

1 голос
/ 10 января 2018

Мы попробовали Установить вместо Список , и это кошмар: когда вы добавляете два новых объекта, равно () и hashCode () не различают их обоих!Поскольку у них нет идентификатора.

типичные инструменты, такие как Eclipse, генерируют такой код из таблиц базы данных:

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

Вы также можете прочитать эту статью , котораяправильно объясняет, как испортился JPA / Hibernate.Прочитав это, я думаю, что это последний раз, когда я использую какой-либо ORM в своей жизни.

Я также встречал ребят из Domain Driven Design, которые в основном говорят, что ORM - ужасная вещь.

1 голос
/ 15 октября 2015

Если у вас слишком сложные объекты с коллекцией saveral, не может быть хорошей идеей иметь все из них с EAGER fetchType, лучше используйте LAZY, а когда вам действительно нужно загрузить коллекции, используйте: Hibernate.initialize(parent.child) для извлечения данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...