Hibernate не может одновременно загружать несколько пакетов

StackOverflow https://stackoverflow.com/questions/4334970

Вопрос

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

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

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

Родитель.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;

}

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


РЕДАКТИРОВАТЬ

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

Родитель.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;

}

ДругойРодитель.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 (благодаря Божо за решение).

Это было полезно?

Решение

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

@LazyCollection(LazyCollectionOption.FALSE)

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

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

Другие советы

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

Добавьте специфичную к гибернации @fetch аннотации к вашему коду:

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

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

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

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

@Fetch(value = FetchMode.SUBSELECT)

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

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

@OneToMany
Set<Your_object> objectList;

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

это сработает.

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

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

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

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

У детей тогда вы должны добавить поле OursiNdex

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

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

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

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

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

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

Типичные инструменты, такие как 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 в моей жизни.

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

Для меня проблема была вложена ЖАЖДУЩИЙ вырвать.

Одно решение - установить вложенные поля в ЛЕНИВЫЙ и используйте Hibernate.initialize () для загрузки вложенного поля:

x = session.get(ClassName.class, id);
Hibernate.initialize(x.getNestedField());

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

@XXXToXXX(targetEntity = XXXX.class, fetch = FetchType.LAZY)

Фактически, значение по умолчанию Fetch является FetchType.Lazy тоже.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top