2012-09-24 16 views
6

मैं इस पैटर्न को बहुत कुछ देखता हूं।पेजिनेटेड प्रश्न/इटेटरेटर रेसिपी

सर्वर पर:

// Get a bounded number of results, along with a resume token to use 
// for the next call. Successive calls yield a "weakly consistent" view of 
// the underlying set that may or may not reflect concurrent updates. 
public<T> String getObjects(
     int maxObjects, String resumeToken, List<T> objectsToReturn); 

ग्राहक पर:

// An iterator wrapping repeated calls to getObjects(bufferSize, ...) 
public<T> Iterator<T> getIterator(int bufferSize); 

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

क्या इन प्रश्नों के लिए एक कैनोलिक रेसिपी या लाइब्रेरी है?

(आप सर्वर-साइड स्टोरेज के लिए कुछ सरल धारणाएं कर सकते हैं, उदाहरण के लिए टी में प्राकृतिक ऑर्डरिंग है)।

public Iterable<T> queryInBatches(
     final String query, 
     final Map<String, Integer> paramMap, 
     final int pageSize, final Class<T> elementType) { 
    return new Iterable<T>() { 
     @Override 
     public Iterator<T> iterator() { 
      final Iterator<List<T>> resultIter = 
        queryResultIterator(query, paramMap, pageSize, elementType); 

      return new AbstractIterator<T>() { 
       private Iterator<T> rowSet; 

       @Override 
       protected T computeNext() { 
        if (rowSet == null) { 
         if (resultIter.hasNext()) { 
          rowSet = resultIter.next().iterator(); 
         } else { 
          return endOfData(); 
         } 
        } 

        if (rowSet.hasNext()) { 
         return rowSet.next(); 
        } else { 
         rowSet = null; 
         return computeNext(); 
        } 
       }}; 
     }}; 
} 


private AbstractIterator<List<T>> queryResultIterator(
     final String query, final Map<String, Integer> paramMap, 
     final int pageSize, final Class<T> elementType) { 
    return new AbstractIterator<List<T>>() { 
     private int page = 0; 

     @Override 
     protected List<T> computeNext() { 
      String sql = String.format(
        "%s limit %s offset %s", query, pageSize, page++ * pageSize); 
      List<T> results = jdbc().queryForList(sql, paramMap, elementType); 
      if (!results.isEmpty()) { 
       return results; 
      } else { 
       return endOfData(); 
      } 
     }}; 
} 

AbstractIteratorIterator का अपना स्वयं का कार्यान्वयन लेखन से जुड़े जटिलताओं का सबसे छुपाता है:

उत्तर

1

यहाँ गूगल-अमरूद पुस्तकालय और वसंत-JDBC से AbstractIterator का उपयोग कर वास्तव में डेटाबेस क्वेरी करने के लिए एक है। आपको केवल computeNext विधि को लागू करने की आवश्यकता है जो या तो इटरेटर में अगला मान देता है या संकेतक में कोई और मूल्य नहीं होने के संकेत देने के लिए endOfData पर कॉल करता है।

+0

मुझे नहीं लगता कि यह अगर dtrt होगा: यह प्रकार टी के तत्वों में से एक इटरेटर

Iterator<List<T>> pagingIterator = new AbstractIterator<List<T>>() { private String resumeToken; private boolean endOfData; @Override protected List<T> computeNext() { if (endOfData) { return endOfData(); } List<T> rows = executeQuery(resumeToken, PAGE_SIZE); if (rows.isEmpty()) { return endOfData(); } else if (rows.size() < PAGE_SIZE) { endOfData = true; } else { resumeToken = getResumeToken(rows.get(PAGE_SIZE - 1)); } return rows; } }; // flatten Iterator of lists to a stream of single elements Stream<T> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(pagingIterator, 0), false) .flatMap(List::stream); // convert stream to Iterator<T> return stream.iterator(); 

यह भी संभव है निम्नलिखित तरीके से विधि संदर्भ का उपयोग करके एक Iterable वापस जाने के लिए रिटर्न तालिका समवर्ती रूप से संशोधित है, क्योंकि सभी बाद के ऑफसेट असंगत होंगे। – ashm

+0

उस स्थिति में आप आईडी काउंटर और ऑफ़सेट का उपयोग करने के बजाय आईडी के लिए एक अतिरिक्त पैरामीटर में प्रवेश करते हैं। कोड संरचना नहीं बदली है। –

1

यहां कुछ ऐसा है जो मेरे लिए काम करता है। यह Google-guava लाइब्रेरी से AbstractIterator का भी उपयोग करता है लेकिन कार्यान्वयन को सरल बनाने के लिए जावा 8 स्ट्रीम का लाभ उठाता है।

// convert stream to Iterable<T> 
return stream::iterator; 
संबंधित मुद्दे

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