2014-07-10 5 views
7

मेरा कोड निम्नलिखित है मैं डेटाबेस से डेटा लाने के लिए कई सूचियों का उपयोग कर रहा हूं। एचक्यूएल क्वेरी से डेटा लाने पर यह अपवाद दिखा रहा है।org.hibernate.loader.MultipleBagFetchException: एक साथ कई बैग नहीं ला सकता

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

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

मैं क्वेरी निम्नलिखित डेटाबेस से डेटा लाने कोशिश कर रहा हूँ, लेकिन यह org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags दिखा रहा है कैसे हल करें ई

+0

आप सेट करने के लिए अपने सूचियाँ बदल रहा करने की कोशिश की है? – JamesB

+0

यह आलेख आपकी मदद कर सकता है: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html – JamesB

+0

बिल प्रोडक्ट पर अद्वितीय आईडी प्रॉपर्टी का नाम क्या है? – JamesB

उत्तर

15

रूप this article में बताया गया है, हाइबरनेट एक से अधिक बैग प्राप्त करने में कठिनाई है क्योंकि वह एक Cartesian product उत्पन्न होगा अनुमति नहीं है।

आप सेट करने के लिए बैग को बदल सकते हैं, और 'अनुकरण' एक आदेश दिया सूची व्यवहार करने के लिए एक order-by="id" विशेषता जोड़ें:

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> 

लेकिन सिर्फ इसलिए कि आप कर सकते हैं, इसका मतलब यह नहीं है कि आप ऐसा करना चाहिए।

आप जो भी कर सकते हैं वह मूल SQL क्वेरी में सबसे अधिक संग्रह में लाया जाता है, जबकि अन्य संग्रह माध्यमिक क्वेरी का उपयोग करके बाद में लाए जाते हैं। इस तरह आप कार्टेशियन उत्पाद से बच सकते हैं।

एक और विकल्प multi-level fetching from child up to parent entities का उपयोग करना है।

+1

मुझे लगता है कि यह लेख 'सेट की http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html की वास्तविक लोडिंग के लिए अधिक प्रासंगिक है। इसके अलावा, सेट में बैग बदलना जॉइन-फ़ेच क्वेरी परिणाम किसी भी कार्टेशियन उत्पाद के कम से कम परिणाम, जो स्वयं बड़े संग्रह के साथ एक मुद्दा हो सकता है। – enlait

0

आपका अनुरोध बहुत अधिक डेटा प्राप्त करता है और हिबरनेट उन्हें सभी लोड नहीं कर सकता है। आपके अनुरोध को कम और/या अपने संस्थाओं आप केवल एक इकाई (या तो billPaidDetailses या billProductList) के लिए एक संबंध निम्नलिखित में शामिल होने-फ़ेच कर सकते हैं बस के लिए आवश्यक डेटा

2

पुनः प्राप्त करने के लिए कॉन्फ़िगर करें।

आलसी संगठनों और लदान संग्रह का उपयोग कर जब वे की जरूरत है, या Hibernate.initialize(..) साथ मैन्युअल रूप से आलसी संगठनों और लदान संग्रह का उपयोग पर विचार करें। कम से कम यह निष्कर्ष था जब मैं similar issue था।

किसी भी तरह से यह डेटाबेस में एक से अधिक क्वेरी लेगा।

+0

सेट करने के लिए सभी सूची को कनवर्ट किया गया मैं सहमत नहीं हूं। कई प्रश्नों के बिना इसे पूरा करने के कई तरीके हैं, क्योंकि अन्य लोगों ने उत्तर दिया है, और कई प्रश्नों के लिए अनुमति देने से कई मामलों में गंभीर प्रदर्शन समस्याएं उत्पन्न होती हैं। –

+0

@ इगोरडोनिन आप सही हैं, यह संभव है। लेकिन यह रजत बुलेट प्रदर्शन-वार नहीं है। कल्पना कीजिए कि मुझे एक कंटेनर लोड करना है, आइए प्रत्येक के 100 तत्वों के 4 सेट कहें। बहुत ज्यादा नहीं, है ना? जॉइन-फ़ेच परिणाम क्वेरी 100000000 – enlait

+0

निश्चित रूप से, आप सही हैं। मैंने ऐसे मामलों को देखा है जिनमें 600 वस्तुओं से अधिक 750000 रिकॉर्ड उत्पन्न किए गए थे। अभी भी संभव है;) –

0

Set पर बदलना सबसे अच्छा समाधान है। हालांकि, अगर आप को Set के साथ प्रतिस्थापित नहीं कर सकते हैं (जैसे मेरे मामले में, Lists पर विशिष्ट जेएसएफ टैग का भारी उपयोग था), और यदि आप हाइबरनेट प्रोप्रायटरी एनोटेशन का उपयोग कर सकते हैं, तो आप @IndexColumn (name = "INDEX_COL") निर्दिष्ट कर सकते हैं। उस समाधान ने मेरे लिए बेहतर काम किया, Set में बदलने के लिए बहुत से रिफैक्टरिंग की आवश्यकता होगी।

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

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

इगोर के रूप में टिप्पणी में सुझाव दिया, आप भी सूचियों वापस जाने के लिए प्रॉक्सी तरीकों बना सकते हैं:

तो, अपने कोड कुछ इस तरह होगा।मैंने कोशिश नहीं की है, लेकिन यदि आप हाइबरनेट मालिकाना एनोटेशन का उपयोग नहीं कर सकते हैं तो यह एक अच्छा विकल्प होगा।

+0

जरूरी नहीं है। आप सेट के लिए अतिरिक्त विधियां जोड़ सकते हैं और उन्हें सूचियों में प्रॉक्सी कर सकते हैं। –

13

मेरे लिए मैं एक ही त्रुटि थी और मैं हाइबरनेट @Fetch का एनोटेशन जोड़कर हल

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER) 
@Fetch(value = FetchMode.SUBSELECT) 
private List<Child> childs; 
संबंधित मुद्दे