2012-10-08 11 views
10

मान लें कि आइटम और बोली संस्थाएं हैं: एक आइटम में कई बोलियां हैं। वे एक ठेठ माता पिता/बच्चे रिश्ते में हाइबरनेट में मैप किया जाता है:मानदंड उत्सुक-संग्रहित संग्रह एन + 1 से बचने के लिए

<class name="Item" table="ITEM"> 
    ... 
    <set name="bids" inverse="true"> 
    <key column="ITEM_ID"/> 
    <one-to-many class="Bid"/> 
    </set> 
</class> 

कैसे जब बाद इस क्वेरी निष्पादित किया जाता है प्रत्येक मद की बोलियों का उपयोग करने की कोशिश कर रहा n + 1 चयन बच सकते हैं?

List<Item> items = session.createCriteria(Item.class) 
         .createAlias("bids", "b"). 
         .add(Restrictions.gt("b.amount", 100)). 
         .list(); 

नोट मैं एक उत्सुक बोलियों के लिए लेकिन संग्रह पर एक और प्रतिबंध के साथ प्राप्त करते समय की जरूरत है (b.amount> 100)

मैं असफल निम्नलिखित की कोशिश की है:

List<Item> items = session.createCriteria(Item.class) 
         .setFetchMode("bids", FetchMode.JOIN). 
         .createAlias("bids", "b"). 
         .add(Restrictions.gt("b.amount", 100)). 
         .list();       

List<Item> items = session.createCriteria(Item.class) 
         .createCriteria("bids") 
         .add(Restrictions.gt("amount", 100)). 
         .list();       
+0

http://stackoverflow.com/questions/617145/hibernate-fetching-strategy-when-to-use-join-and-when-to-use-select मुझे लगता है कि इससे पहले पूछा जा रहा है .... –

उत्तर

6

यही कारण है कि लाने-में शामिल हो गए संग्रह पर एक प्रतिबंध को जोड़ने का कारण बनता संग्रह प्रारंभ नहीं किया गया था की एक विवरण (टिप्पणी कि प्रतिबंध के बिना एक ही क्वेरी एक उत्सुक संग्रह के लिए लाने का उत्पादन) है:

"यदि आपके पास टेबल ए और बी के बीच 1: n संबंध है, और आप बी पर प्रतिबंध जोड़ते हैं और ए और बी को उत्सुकता से प्राप्त करना चाहते हैं, तो सवाल तब होगा जब आप ए से नेविगेट करना चाहते हैं बी क्या आपको केवल बी में डेटा देखना चाहिए जो प्रतिबंध से मेल खाता है, या आप संबंधित सभी बीएस देखना चाहिए ए के लिए? " see more here ...

हालांकि, मापदंड के बजाय HQL का उपयोग कर, आंशिक रूप से बोलियां संग्रह

List<Item> items = session.createQuery(
      "from Item i left join fetch i.bids b where b.amount > :amount") 
      .setParameter("amount", 100) 
      .list(); 

यह मुझे कोई विसंगति करने लगता है, लेकिन यह यह कैसे काम करता

वैसे है लाने, यदि आपको जो चाहिए वह माता-पिता और उसके सभी बच्चों की सूची है, लेकिन केवल माता-पिता जिनके बच्चे सभी प्रतिबंधों को पूरा करते हैं, तो आप इस

का उपयोग कर सकते हैं
List<Item> items = session.createQuery(
      "from Item i left join fetch i.bids b " + 
      "where not exists (from Bid b where b.item = i and b.amount <= :amount)") 
      .setParameter("amount", 100) 
      .list(); 

यह एक संबंधित पोस्ट है: Hibernate query not returning full object

9

यह मानदंड क्वेरी सही लगता है:

List<Item> items = session.createCriteria(Item.class) 
        .setFetchMode("bids", FetchMode.JOIN) 
        .createAlias("bids", "b") 
        .add(Restrictions.gt("b.amount", 100)) 
        .list(); 

FetchMode.JOINn+1 समस्या हल करने के लिए है। क्या आपने कुछ default_batch_fetch_size परिभाषित किया है batch-size मैपिंग या कॉन्फ़िगरेशन में कहीं भी, जो रिवर्स इफेक्टिंग है?

यदि नहीं, तो क्या आप कृपया एचक्यूएल के नीचे आज़माएं और देखें कि यह आपकी समस्या हल करता है?

Query query = 
     session.createQuery("from Item it left join it.bids b where b.amount=:bids"); 
query.setParamter(bids, 100); 
List<Item> items = query.list(); 
1

मुझे लगता है कि आपको जो चाहिए वह एक मानदंड है जो अन्य मानदंडों पर सबक्वायरी मौजूदियों का उपयोग करता है।ऐसा ही एक जवाब यहाँ है: https://stackoverflow.com/a/15768089/1469525

DetachedCriteria criteria = session.createCriteria(Item.class, "i"); 
criteria.setFetchMode("bids", FetchMode.JOIN); 

DetachedCriteria bidCriteria = DetachedCriteria.forClass(Bid.class, "b"); 
bidCriteria.add(Restrictions.gt("amount", 100)); 
bidCriteria.add(Restrictions.eqProperty("b.itemId", "i.id")); 
criteria.add(Subqueries.exists(bidCriteria.setProjection(Projections.property("b.id"))));