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
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 .
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;
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.
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.
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
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