Błąd – cannot simultaneously fetch multiple bags


Błąd – cannot simultaneously fetch multiple bags

Więcej niż jedna kolekcja typu List z ustawionym parametrem:

 fetch = FetchType.EAGER

w implementacji JPA jaką jest Hibernate doprowadzi do błędu:

“cannot simultaneously fetch multiple bags, a list can be known as bag”.

@Entity
public class Person {
    @Id
    private int id;

    private String name ;
    
    @OneToMany (mappedBy = " person ", fetch = FetchType . EAGER )
    private List < Friend > friends ;

    @OneToMany (mappedBy = " person ", fetch = FetchType . EAGER )
    private List < Skills > skills ;
    // getter and setetter
}

Hibernate traktuje typ List jako typ Bag – “nieposortowana lista”. Pobierając rekordy zachłannie czyli używając opcji EAGER, Hibernate pobiera wszystkie rekordy w momencie kiedy następuje odwołanie do encji nadrzędnej. Stosowane jest przy tym złączenie LEFT OUTER JOIN. Hibernate na podstawie wyniku zapytania nie jest w stanie jednoznacznie stwierdzić ile rekordów zostało zwróconych dla listy skills. Bardziej szczegółowo, dwie listy:

@OneToMany ( mappedBy =" parent ",cascade = CascadeType .ALL , fetch = FetchType . EAGER )
List < Child1 > child1s = new LinkedList < Child1 >();

@OneToMany ( mappedBy =" parent ",cascade = CascadeType .ALL , fetch = FetchType . EAGER )
List < Child2 > child2s = new LinkedList < Child2 >();

Hibernate wykona zapytanie:

select
parent0_ .id as p_id , parent0_ . name as p_name , child1s1_ . parent_id
as c1_p_id , child1s1_ .id as c1_id , child1s1_ .id as c1_id_1 ,
child1s1_ . parent_id as c1_p_id_1 , child1s1_ . value as c1_val ,
child2s2_ . parent_id as c2_p_id , child2s2_ .id as c2_id ,
child2s2_ .id as c2_id_ , child2s2_ . parent_id as
c2_p_id_1 , child2s2_ . value as c2_val
from
PARENT parent0_ left outer join
CHILD1 child1s1_ on parent0_ .id= child1s1_ . parent_id left outer join
CHILD2 child2s2_ on parent0_ .id= child2s2_ . parent_id
where
parent0_ .id =?

Załóżmy, że zawartość tabel jest następująca:

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

W wyniku zapytania (po podstawieniu wartości 122 jako parent0_ .id =?) Hibernate nie jest w stanie stwierdzić że w tabeli CHILD2 znajduje się dokładnie jeden rekord. Wynik zapytania wyraźnie wskazuje, że są to dwa identyczne rekordy. Dochodzi zatem do niejednoznaczności która skutkuje tytułowym błędem “cannot simultaneously fetch multiple bags“. Rozwiązanie? Powinniśmy zdecydowanie w naszych aplikacjach maksymalizować wykorzystanie typu Set:

@OneToMany ( mappedBy =" parent ",cascade = CascadeType .ALL , fetch = FetchType . EAGER )
Set< Child1 > child1s = new LinkedList < Child1 >();

@OneToMany ( mappedBy =" parent ",cascade = CascadeType .ALL , fetch = FetchType . EAGER )
Set< Child2 > child2s = new LinkedList < Child2 >();

 


Leave a comment

Your email address will not be published.


*