2011-04-06 13 views
8

हाइबरनेट ctiteria का उपयोग करके मैं एक वस्तु का चयन करना चाहता हूं और यह ऑब्जेक्ट्स की एक टोनी सूची से जुड़ा हुआ है। मैं डरावनी हाइबरनेट एन + 1 चुनिंदा समस्या से बचने के लिए इस सूची के माध्यम से पेजिंग करना चाहता हूंहाइबरनेट मानदंड एन + 1 अंक maxresults

यहां एक कामकाजी समाधान है जिसके लिए 10 मूल वस्तुओं के लिए डेटाबेस में 11 ट्रिप की आवश्यकता है।

Criteria criteria = this.getSession().createCriteria(Mother.class); 
criteria.addOrder(Order.asc("title")) 
.setMaxResults(details.getMaxRows()) 
.setFirstResult(details.getStartResult()) 
.setFetchMode("kittens", FetchMode.SELECT); 
List test = criteria.list(); 

और यहाँ एक समाधान है जो केवल एक एसक्यूएल बयान (हुर्रे) निष्पादित करता है लेकिन पृष्ठांकन संभाल सकते हैं यानी setMaxResults और setFirstResult पैरेंट ऑब्जेक्ट माँ (बू) पर सही नहीं हैं

Criteria criteria = this.getSession().createCriteria(Mother.class); 
criteria.addOrder(Order.asc("title")) 
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 
.setMaxResults(details.getMaxRows()) 
.setFirstResult(details.getStartResult()) 
.setFetchMode("kittens", FetchMode.JOIN); 
List test = criteria.list(); 

इस तरह की तरह लगता है है एक आम आवश्यकता है लेकिन मैंने बिना किसी किस्मत के समाधान के लिए खोद दिया है।

कोई भी लेकर्स?

उत्तर

15

1 क्वेरी के लिए नीचे हो रही है कठिन है (यानी मैं एक पोर्टेबल समाधान पता नहीं है), लेकिन यह नीचे हो रही 2 प्रश्नों का (एन पर ध्यान दिए बिना) बहुत सरल है:

Criteria criteria = this.getSession().createCriteria(Mother.class); 
criteria.addOrder(Order.asc("title")) 
    .setMaxResults(details.getMaxRows()) 
    .setFirstResult(details.getStartResult()) 
    .setProjection(Projections.id()); 
List<?> ids = criteria.list(); 

criteria = getSession().createCriteria(Mother.class) 
    .add(Restrictions.in("id", ids)) 
    .setFetchMode("children", FetchMode.JOIN) 
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 

return criteria.list(); 

कुछ डेटाबेस के लिए, सबसिलेक्ट प्राप्त करने में कठिनाई children काम हो सकता है, भी।

+0

ग्रेट उत्तर। धन्यवाद और सम्मान। – jaseFace

+0

मेरी इच्छा है कि मैं इसे एक से अधिक बार बढ़ा सकता हूं। चालाक कामकाज। – cdmckay

+0

ग्रेट एंडवर; मेरे मामले में मुझे कई लोगों में शामिल होने के कारण दोहराया गया, इसलिए मैंने लाइन 5 पर प्रक्षेपण को '.setProjection (Projections.distinct (Projections.id()) के साथ बदल दिया)' –

2

जहाँ तक मुझे पता के रूप में देशी SQL क्वेरी के साथ निम्नलिखित चाल के अलावा इस समस्या को हल करने के लिए कोई अच्छा तरीके (सटीक SQL सिंटैक्स अपने डीबीएमएस पर निर्भर करता है) देखते हैं:

List<Mother> result = s.createSQLQuery(
    "select {m.*}, {k.*} " + 
    "from (select limit :firstResult :maxResults * from Mother m) m " + 
    "left join Kitten k on k.motherId = m.id" 
    ) 
    .addEntity("m", Mother.class) 
    .addJoin("k", "m.kittens") 
    .setParameter("firstResult", ...) 
    .setParameter("maxResults", ...) 
    .setResultTransformer(MyDistrictRootEntityResultTransformer.INSTANCE) 
    .list(); 

... 

// Unfortunately built-in DistrictRootEntityResultTransformer cannot be used 
// here, since it assumes that root entity is the last in the tuple, whereas 
// with addEntity()/addJoin() it's the first in the tuple 
public class MyDistrictRootEntityResultTransformer implements ResultTransformer { 
    public static final MyDistrictRootEntityResultTransformer INSTANCE = new MyDistrictRootEntityResultTransformer(); 

    public Object transformTuple(Object[] tuple, String[] aliases) { 
     return tuple[0]; 
    } 

    public List transformList(List collection) { 
     return DistinctResultTransformer.INSTANCE.transformList(collection); 
    } 
} 
+0

यह बेहतर समाधान है। केवल एक एसक्यूएल कॉल। – IvanNik

संबंधित मुद्दे