cannot simultaneously fetch multiple bags

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

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

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

Parent.java

Child.java

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

ИЗМЕНИТЬ

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

Java, JEE, Docker and software architecture related techniques, HOWTOs, thoughts and more

Содержание

  1. Hibernate Exception — Simultaneously Fetch Multiple Bags
  2. So what is the problem?
  3. Workarounds
  4. Comments
  5. igdianov commented Sep 21, 2017
  6. This comment has been minimized.
  7. igdianov commented Sep 21, 2017

Hibernate Exception — Simultaneously Fetch Multiple Bags

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

One of my customers has just upgraded to JBoss 4.0.4-GA, the process also required us to upgrade Hibernate products to the following versions:

  • Hibernate core – 3.2.0CR2
  • Hibernate Entity Manager – 3.2.0CR1
  • Hibernate annotations- 3.2.0CR1

We fixed some minor changes and improvements and then we bumped into the following exception

The Exception is thrown by org.hibernate.loader.BasicLoader and it means that when loading an entity Hibernate might has to simultaneously fetch two or more bags.

So what is the problem?

When an entity has more than one non-lazy association that might be interpreted as a bag (e.g., java.util.List or java.util.Collection properties annotated with @org.hibernate.annotations.CollectionOfElements or @OneToMany or @ManyToMany and not annotated with @org.hibernate.annotations.IndexColumn) hibernate will fail to fetch the entity correctly.
Lets say that we have a Parent class, and two children classes (Child1 and Child2), the parent class has a bag for each of the children types, as illustrated by the following mapping

We have to notice the bag semantic and the EAGER fetching on both associations, the cascading is not important to our problem. When parsing the mapping Hibernate pre-build the following (I changed the columns aliases for readability) SQL

Now assume the following data in our database

PARENT table ID NAME 122 PARENT-1 CHILD1 table ID VALUE PARENT_ID 123 CHILD1-1 122 1 CHILD1-2 122 CHILD2 table ID VALUE PARENT_ID 124 CHILD2-1 122

Replacing the question mark with 122 and execute the above select statement yields the following result

P_ID P_NAME C1_P_ID C1_ID C1_ID_1 C1_P_ID_1 C1_VAL C2_P_ID C2_ID C2_ID_ C2_P_ID_1 C2_VAL 122 Parent-1 122 123 123 122 CHILD1-1 122 124 124 122 CHILD2-1 122 Parent-1 122 1 1 122 CHILD1-2 122 124 124 122 CHILD2-1

As we can see there is no why Hibernate can understand from the query result that the Child2 bag has only one element, it thinks it has two identical elements(!) — the red cells.
One more comment

  • In the JIRA it says that in the future Hibernate might fall back to sub-select strategy

Workarounds

I’ve found three strategies to overcome this issue, the first one is to use LAZY fetching when possible. I don’t even have to change all of my associations to be lazy fetched, I just can’t have more than one EGAR association on the same entity. The second solution is to replace bag semantics with List semantics this can be done by adding the @IndexColumn on the relation.

The usage of @IndexColumn helps solving the problem since now Hibernate has a List semantic for the association and when fetching the parent it also fetches the index of each element on the list. Using this index Hibernate can tell if the element on the list has already been loaded. We have to remember that by adding @IndexColumn on the inverse side of an association (as illustrated above) we have to maintain the index “by hand”, Hibernate doesn’t maintain the index on the inverse side of the relation (I’ll explain how we can instruct Hibernate to maintain such an index on one of the next entries in my OLD blog).

Comments

Copy link Quote reply

igdianov commented Sep 21, 2017

produces the following exception with the stack trace:

This comment has been minimized.

Copy link Quote reply

igdianov commented Sep 21, 2017

When we use Collection or List type in @ManyToMany or @OneToMany associations like below

Hibernate underneath JPA cannot use java.util.List or java.util.Collection for fetching eagerly associations with more than two levels of nesting for collections while using generated fetch graph to optimize query performance.

One workaround solution is to replace bag semantics with List semantics. This can be done by adding the @IndexColumn on the relation. The usage of @IndexColumn helps solving the problem since now Hibernate has a List semantic for the association and when fetching the parent it also fetches the index of each element on the list. Using this index Hibernate can tell if the element on the list has already been loaded

Источник: computermaker.info

Понравилась статья? Поделиться с друзьями:
Ок! Компьютер
Добавить комментарий