Hibernate выбрасывает это исключение во время создания SessionFactory:
org.hibernate.loader.MultipleBagFetchException: не может одновременно извлекать несколько пакетов
Это мой тестовый пример:
Parent.java
Child.java
Как насчет этой проблемы? Что я могу сделать?
ИЗМЕНИТЬ
Хорошо, проблема заключается в том, что другой родительский объект внутри моего родителя, мое реальное поведение таково:
Java, JEE, Docker and software architecture related techniques, HOWTOs, thoughts and more
Содержание
- Hibernate Exception — Simultaneously Fetch Multiple Bags
- So what is the problem?
- Workarounds
- Comments
- igdianov commented Sep 21, 2017
- This comment has been minimized.
- igdianov commented Sep 21, 2017
Hibernate Exception — Simultaneously Fetch Multiple Bags
- Get link
- 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
Replacing the question mark with 122 and execute the above select statement yields the following result
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
Источник: