org.hibernacja.ładowacz.MultipleBagFetchException: nie można jednocześnie pobrać wielu toreb

Poniżej znajduje się mój kod tutaj używam wielu list do pobierania danych z bazy danych. Przy pobieraniu danych z zapytania hql wyświetla się wyjątek.

Klasa Pojo

public class BillDetails implements java.io.Serializable {

private Long billNo;
// other fields
@LazyCollection(LazyCollectionOption.FALSE)
private List<BillPaidDetails> billPaidDetailses = new ArrayList<BillPaidDetails>();
private Set productReplacements = new HashSet(0);
@LazyCollection(LazyCollectionOption.FALSE)
private List<BillProduct> billProductList = new ArrayList<BillProduct>();
//getter and setter
}

Hmb.plik xml

<class name="iland.hbm.BillDetails" table="bill_details" catalog="retail_shop">
        <id name="billNo" type="java.lang.Long">
            <column name="bill_no" />
            <generator class="identity" />
        </id>
 <bag name="billProductList" table="bill_product" inverse="true" lazy="false" fetch="join">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.BillProduct" />
        </bag>
        <bag name="billPaidDetailses" table="bill_paid_details" inverse="true" lazy="false" fetch="select">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.BillPaidDetails" />
        </bag>
        <set name="productReplacements" table="product_replacement" inverse="true" lazy="false" fetch="join">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.ProductReplacement" />
        </set>
    </class>

Zapytanie Hql

String hql = "select distinct bd,sum(bpds.amount) from BillDetails as bd "
                    + "left join fetch bd.customerDetails as cd "
                    + "left join fetch bd.billProductList as bpd "
                    + "left join fetch bpd.product as pd "
                    +"left join fetch bd.billPaidDetailses as bpds "
                    + "where bd.billNo=:id "
                    + "and bd.client.id=:cid ";

Próbuję wykonać zapytanie, aby pobrać dane z bazy danych, ale to pokazuje org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags Jak rozwiązać ten

Author: Vlad Mihalcea, 2014-07-10

5 answers

Jak wyjaśniono w w tym artykule , Hibernate nie pozwala na pobieranie więcej niż jednego worka, ponieważ generowałoby to iloczyn kartezjański .

Możesz zmienić worki na zestawy i dodać atrybutorder-by="id", aby 'symulować' uporządkowane zachowanie listy:

private Set<BillPaidDetails> billPaidDetailses = new LinkedHashSet<>();
private Set<BillProduct> billProductList = new LinkedHashSet<>();

<set name="billProductList" table="bill_product" 
     inverse="true" lazy="false" fetch="join" order-by="id">
    <key>
        <column name="bill_no" not-null="true" />
    </key>
    <one-to-many class="iland.hbm.BillProduct" />
</set>

<set name="billPaidDetailses" table="bill_paid_details" 
     inverse="true" lazy="false" fetch="select" order-by="id">
    <key>
        <column name="bill_no" not-null="true" />
    </key>
    <one-to-many class="iland.hbm.BillPaidDetails" />
</set>

Ale to, że możesz, nie znaczy, że powinieneś.

To, co możesz zrobić, to pobrać co najwyżej jedną kolekcję w oryginalnym zapytaniu SQL, podczas gdy pozostałe kolekcje są pobierane później za pomocą zapytania wtórne. W ten sposób można uniknąć iloczynu kartezjańskiego.

Inną opcją jest użycie wielopoziomowego pobierania od dziecka do jednostek nadrzędnych .

 19
Author: Vlad Mihalcea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 12:00:22

U mnie ten sam błąd i rozwiązałem dodając adnotację hibernate @ Fetch

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;
 16
Author: BERGUIGA Mohamed Amine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-19 16:24:12

możesz tylko join-fetch po jednej relacji dla encji (billPaidDetailses lub billProductList).

Rozważ używanie leniwych skojarzeń i ładowanie kolekcji, gdy są potrzebne, lub używanie leniwych skojarzeń i ładowanie kolekcji ręcznie za pomocą Hibernate.initialize(..). Przynajmniej do takiego wniosku doszedłem, gdy miałem podobny problem .

tak czy inaczej, do bazy danych zostanie wysłane więcej niż jedno zapytanie.

 2
Author: enlait,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:01

Zmiana na Set jest najlepszym rozwiązaniem. Jednakże, jeśli nie możesz nie zastąpić List Set (Jak w moim przypadku, było duże użycie znaczników JSF specyficznych dla Lists), a jeśli możesz użyć zastrzeżonych adnotacji Hibernate, możesz podać @IndexColumn (name = "INDEX_COL"). To rozwiązanie działało dla mnie lepiej, zmiana na Set wymagałaby mnóstwa refaktoryzacji.

Więc Twój kod będzie taki:

@IndexColumn (name = "INDEX_COL")
private List<BillPaidDetails> billPaidDetailses = new ArrayList<BillPaidDetails>();

@IndexColumn (name = "INDEX_COL")
private List<BillProduct> billProductList = new ArrayList<BillProduct>();

Jak zasugerował Igor w komentarzach, można również utworzyć metody proxy, aby zwrócić listy. Nie próbowałem tego, ale byłoby dobrą alternatywą, jeśli nie możesz użyć zastrzeżonych adnotacji Hibernate.

 1
Author: L. Holanda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-20 17:52:47

Twoje żądanie pobiera zbyt wiele danych i HIbernate nie może załadować ich wszystkich. Zmniejsz żądanie i / lub skonfiguruj jednostki, aby pobierały tylko potrzebne dane

 0
Author: Pracede,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-10 11:33:00