15

मैं वर्तमान में एक आरईएसटी एपीआई बना रहा हूं जिसमें मैं चाहता हूं कि क्लाइंट आसानी से किसी विशिष्ट इकाई के अधिकांश गुणों पर फ़िल्टर करें। QueryDSLSpring Data REST (an example by Oliver Gierke) के साथ संयोजन में उपयोग करने से मुझे गुणों का संदर्भ देने वाले क्वेरी पैरामीटर को जोड़कर फ़िल्टर करने की अनुमति देकर 90% तक आसानी से प्राप्त करने की अनुमति मिलती है (उदा। /users?firstName=Dennis&lastName=Laumen)।क्या वसंत डेटा आरईएसटी के क्वेरीएसएलएल एकीकरण का उपयोग अधिक जटिल प्रश्नों के लिए किया जा सकता है?

मैं QuerydslBinderCustomizer इंटरफ़ेस को लागू करके क्वेरी पैरामीटर और इकाई के गुणों के बीच मैपिंग को भी कस्टमाइज़ कर सकता हूं (उदाहरण के लिए असंवेदनशील खोज या आंशिक स्ट्रिंग मैचों के मामले में)। यह सब अच्छा है, हालांकि मैं यह भी चाहता हूं कि क्लाइंट रेंज का उपयोग करके कुछ प्रकार फ़िल्टर कर सकें। उदाहरण के लिए जन्म की तारीख जैसी संपत्ति के संबंध में मैं निम्नलिखित, /users?dateOfBirthFrom=1981-1-1&dateOfBirthTo=1981-12-31 जैसे कुछ करना चाहता हूं। यह संख्या आधारित गुणों के लिए जाता है, /users?idFrom=100&idTo=200। मुझे लगता है कि QuerydslBinderCustomizer इंटरफ़ेस का उपयोग करके यह संभव होना चाहिए लेकिन इन दोनों पुस्तकालयों के बीच एकीकरण बहुत व्यापक रूप से दस्तावेज नहीं किया गया है।

निष्कर्ष, क्या यह स्प्रिंग डेटा आरईएसटी और क्वेरीडीएसएल का उपयोग कर संभव है? यदि हां, तो कैसे?

उत्तर

19

मुझे लगता है कि आप इस निम्नलिखित अनुकूलन का उपयोग करते काम करने के लिए प्राप्त करने के लिए सक्षम होना चाहिए:

bindings.bind(user.dateOfBirth).all((path, value) -> { 

    Iterator<? extends LocalDate> it = value.iterator(); 
    return path.between(it.next(), it.next()); 
}); 

कुंजी यहाँ ?dateOfBirth=…&dateOfBirth= उपयोग करने के लिए और ….all(…) बंधन है जो आप दे देंगे (संपत्ति दो बार का उपयोग करें) है प्रदान किए गए सभी मूल्यों तक पहुंच।

सुनिश्चित करें कि आप User की dateOfBirth -property को @DateTimeFormat टिप्पणी जोड़ने के लिए इतना है कि वसंत भेजे StringsLocalDate में उदाहरणों सही ढंग से बदलने में सक्षम है।

लैम्ब्डा वर्तमान में एक Collection<? extends T> जो थोड़ा अधिक दर्द अलग-अलग तत्वों है कि यह होने की जरूरत है untangling बनाता हो जाता है, लेकिन मुझे लगता है कि हम एक भविष्य के रिलीज बल्कि एक List का पर्दाफाश करने में बदल सकते हैं।

+0

धन्यवाद @ oliver-gierke! मुझे आपके द्वारा दिए गए उदाहरण के आधार पर काम करने के लिए मिला और कुछ और सशर्त तर्क जोड़ा गया ताकि अगर केवल एक तारीख दी जाती है तो इसे "से" तिथि के रूप में उपयोग किया जाता है। क्या आप कुछ और अतिरिक्त स्पष्टीकरण दे सकते हैं कि क्या यह * बाध्यकारी के लिए मौजूद अस्तित्व को जोड़ना भी संभव है? क्या स्प्रिंग डेटा आरईएसटी और क्वेरीडीएसएल का उपयोग करके "dateOfBirthFrom" क्वेरी पैरामीटर को जोड़ने का मेरा उदाहरण भी है? (बस उत्सुक, आपने पहले से ही मेरी समस्या हल की है! धन्यवाद!) –

+1

@DennisLaumen "dateOfBirthFrom" शैली क्वेरी पैरामीटर सहायक हो सकता है। आपकी क्वेरी बाइंडिंग अनुकूलन मानती है कि यदि तारीख से ही उपयोग की जाने वाली केवल एक तारीख है, है ना? लेकिन सिर्फ एक तारीख का उपयोग करके फ़िल्टर करना संभव नहीं होगा। कोई सुझाव @ oliver-gierke? – gazal

+0

@gazal, मैंने इसे निम्नलिखित कोड का उपयोग करके तय किया है, उम्मीद है कि यह मदद करता है। 'bindings.bind (Date.class) सब के सब ((DateTimePath पथ, संग्रह मूल्य) -> { इटरेटर <फैली दिनांक> यह value.iterator() =;? दिनांक firstTimestamp = it.next(); अगर (it.hasNext()) { दिनांक secondTimestamp = it.next(); वापसी path.between (firstTimestamp, secondTimestamp); } else { वापसी path.after (firstTimestamp) ; } }); ' –

3

यही वह है जो मैंने सभी दिनांक फ़ील्ड के लिए सामान्य बाध्यकारी के लिए उपयोग किया था, हमेशा से 2 मानों की अपेक्षा करता था।

bindings.bind(Date.class).all((final DateTimePath<Date> path, final Collection<? extends Date> values) -> { 
    final List<? extends Date> dates = new ArrayList<>(values); 
    Collections.sort(dates); 
    if (dates.size() == 2) { 
     return path.between(dates.get(0), dates.get(1)); 
    } 
    throw new IllegalArgumentException("2 date params(from & to) expected for:" + path + " found:" + values); 
}); 

यह डेटाटाइम फ़ील्ड के लिए है। दिनांक फ़ील्ड के लिए, एक पैरामीटर प्राप्त करते समय, path.eq() मुझे लगता है कि समझ में आता है।

5

जैसा कि इसे कुछ टिप्पणी में पोस्ट किया गया था, मुझे फ़ील्ड नाम creationDateFrom और creationDateTo के अनुसार अलग-अलग व्यवहार करने की आवश्यकता भी थी। इसे काम करने के लिए मैंने निम्नलिखित किया:

सबसे पहले मैंने @QueryEntity एनोटेशन और मेरी इकाई वर्ग में दो और फ़ील्ड जोड़े।क्षेत्रों के साथ एनोटेट गया:

  • @Transient तो खेतों
  • @Getter(value = AccessLevel.PRIVATE) कायम नहीं कर रहे हैं के रूप में हम लंबोक उपयोग कर रहे हैं, एनोटेशन प्रतिक्रिया शरीर से क्षेत्र छुपाता
  • @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) पार्सिंग के लिए प्रारूप का ख्याल रखता है यूआरएल क्वेरी पैरामीटर

@QueryEntity 
@Entity 
public class MyEntity implements Serializable { 
    ... 

    @Column(updatable = false) 
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
    private Date creationDate; 

    @Transient 
    @Getter(value = AccessLevel.PRIVATE) 
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
    private Date creationDateTo; 

    @Transient 
    @Getter(value = AccessLevel.PRIVATE) 
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
    private Date creationDateFrom; 

    ... 
} 
0 पर तारीख

फिर मैंने क्वेरीएसएल कक्षाओं को JPAAnnotationProcessor से QuerydslAnnotationProcessor से उत्पन्न करने का तरीका बदल दिया। इस प्रकार @Transient के साथ एनोटेटेड फ़ील्ड्स अभी भी QMyEntity पर जेनरेट किए गए हैं लेकिन जारी नहीं हैं। पोम में प्लगइन विन्यास:

<plugin> 
    <groupId>com.mysema.maven</groupId> 
    <artifactId>apt-maven-plugin</artifactId> 
    <version>1.1.3</version> 
    <executions> 
     <execution> 
      <phase>generate-sources</phase> 
      <goals> 
       <goal>process</goal> 
      </goals> 
      <configuration> 
       <outputDirectory>target/generated-sources/annotations</outputDirectory> 
       <processor>com.querydsl.apt.QuerydslAnnotationProcessor</processor> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

अंत में मैं QuerydslBinderCustomizer बढ़ाया और creationDateFrom और creationDateTo लेकिन इस समय अवधि के लिए कर सकते हैं के सभी के साथ creationDate

@Override 
default void customize(QuerydslBindings bindings, QMyEntity root) { 
    bindings.bind(root.creationDateFrom).first((path, value) -> 
               root.creationDate.after(value)); 
    bindings.bind(root.creationDateTo).first((path, value) -> 
               root.creationDate.before(value)); 
} 

से अधिक सही तर्क लागू करने के साथ संबंधित बाइंडिंग अनुकूलित एक, दोनों या किसी भी मानदंड का उपयोग करने वाले प्रश्न:

http://localhost:8080/myentities?creation_date_to=2017-05-08 
http://localhost:8080/myentities?creation_date_from=2017-01-01 
http://localhost:8080/myentities?creation_date_from=2017-01-01&creation_date_to=2017-05-08 
संबंधित मुद्दे