2014-10-07 6 views
11

मेरे पास स्प्रिंग डेटा जेपीए (हाइबरनेट बैकएंड) रिपॉजिटरी कक्षाओं के साथ एक स्प्रिंग बूट ऐप है। मैंने कुछ कस्टम खोजक विधियों को जोड़ा है, कुछ विशिष्ट @Query एनोटेशन के साथ यह बताते हैं कि डेटा कैसे प्राप्त करें। मैंने पहले से ही हाइबरनेट द्वितीय स्तर के कैश के लिए एएच कैश स्थापित कर लिया है, लेकिन अब तक, इन परिणामों को कैशिंग प्राप्त करने का एकमात्र तरीका है हाइबरनेट क्वेरी कैश को सक्षम करना। मैं एक विशिष्ट कैश को परिभाषित करना और वास्तविक डोमेन ऑब्जेक्ट्स को वहां स्टोर करना पसंद करूंगा जैसे कि यह एक सामान्य खोजक था।क्वेरी कैश का उपयोग किए बिना स्प्रिंग डेटा जेपीए क्वेरी विधि के परिणामों को कैसे कैश करें?

public interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> { 

    @Query("SELECT psx FROM Customer c " + 
     "JOIN c.customerProductPromotions cpp " + 
     "JOIN cpp.productPromotion pp " + 
     "JOIN pp.promotion p JOIN p.promotionServiceXrefs psx " + 
     "WHERE c.customerId = ?1") 
    @QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true")) 
    @Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "promotionServiceXrefByCustomerId") 
    Set<PromotionServiceXref> findByCustomerId(int customerId); 
} 

यहाँ और "promotionServiceXrefByCustomerId" कैश मैं परिभाषित किया गया है, कि नहीं किया जा रहा है: नीचे मेरी रेपो कोड है

<cache name="promotionServiceXrefByCustomerId" overflowToDisk="true" diskPersistent="true" 
     maxEntriesLocalHeap="3000000" eternal="true" diskSpoolBufferSizeMB="20" memoryStoreEvictionPolicy="LFU" 
     transactionalMode="off" statistics="true"> 
</cache> 

क्या मैं गलत कर रहा हूँ? यदि मैं StandardQueryCache सक्षम करता हूं तो यह डेटा वहां कैश हो जाता है और हाइबरनेट क्वेरी निष्पादित नहीं करता है। लेकिन जब मैं क्वेरी कैशिंग अक्षम करता हूं, तो यह कैश नहीं होता है। मुझसे यहां क्या गलत हो रहा है? कृपया सहायता कीजिए!

+0

'@ कैश' एनोटेशन किसी गैर इकाई के लिए कुछ क्यों करना चाहिए? यह एनोटेशन इकाइयों पर मनमाने ढंग से कक्षाओं या इंटरफेस पर नहीं है। –

+0

मैं इसे समझने की कोशिश कर रहा हूं ... इसलिए किसी भी मदद की सराहना की जाएगी। अन्य ढूंढें ... स्प्रिंग द्वारा रनटाइम पर बनाए गए पेजिंग एंड सोर्सिंग रिपोजिटरी में निर्दिष्ट विधियां जेपीए/हाइबरनेट के दूसरे स्तर के कैशिंग का उपयोग करके कैशिंग प्रदान करती हैं। यह ठीक से काम करता है। लेकिन मैंने यह खोजक तरीका बनाया है, मैं यह नहीं समझ सकता कि आईटी को कैश कैसे प्राप्त किया जाए ... –

+1

मुझे संदेह है कि 'findAll' कैशिंग है जब तक कि आप अपनी संस्थाओं पर नॉटेशन न हो (जहां उन्हें जाना चाहिए)। यदि आप एक गैर-कैश करने योग्य इकाई को कैश करने की कोशिश कर रहे हैं (या उम्मीद कर रहे हैं) यह काम नहीं करेगा, केवल उस मामले में क्वेरी कैश काम करेगा। –

उत्तर

35

आपके पास जो कोड है वह काम नहीं कर रहा है यह है कि @Cache इस तरह से काम करने का इरादा नहीं है। यदि आप क्वेरी विधि निष्पादन के परिणामों को कैश करना चाहते हैं, तो सबसे आसान तरीका वसंत के caching abstraction का उपयोग करना है।

interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> { 

    @Query("…") 
    @Cacheable("servicesByCustomerId") 
    Set<PromotionServiceXref> findByCustomerId(int customerId); 

    @Override 
    @CacheEvict(value = "servicesByCustomerId", key = "#p0.customer.id") 
    <S extends PromotionServiceXref> S save(S service); 
} 

इस सेटअप का कारण होगा findByCustomerId(…) के लिए कॉल के परिणामों ग्राहक पहचानकर्ता द्वारा संचित किया जा। ध्यान दें, हमने @CacheEvict को ओवरराइड save(…) विधि में जोड़ा है, ताकि जब भी कोई इकाई सहेजी जाती है, तो क्वेरी विधि के साथ हम जिस कैश को पॉप्युलेट करते हैं, उसे निकाल दिया जाता है। इसे शायद delete(…) विधियों के साथ प्रचारित किया जाना है।

अब आप आगे एक कॉन्फ़िगर एक समर्पित CacheManager (विवरण के लिए reference documentation देखें) (यहाँ एक सादे ConcurrentHashMap का उपयोग) में जो भी कैशिंग समाधान आप पसंद करते हैं प्लग करने के लिए जा सकते हैं।

@Configuration 
@EnableCaching 
class CachingConfig { 

    @Bean 
    CacheManager cacheManager() { 

    SimpleCacheManager cacheManager = new SimpleCacheManager(); 
    cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("servicesByCustomerId))); 

    return cacheManager; 
    } 
} 
+0

धन्यवाद। मैंने इस मार्ग पर जाना शुरू कर दिया लेकिन एक मुद्दे में भाग गया जब मेरे पास कक्षा में कई विधियां थीं जिनके लिए मुझे कैशिंग अबास्ट्रक्शन की आवश्यकता थी, लेकिन वास्तव में उसी कक्षा में किसी अन्य विधि से बुलाया गया था। मुझे AspectJ मार्ग जाने की आवश्यकता होगी। यह पता चला, मैंने इस डेटा को व्यावसायिक कारणों से कैश करने की आवश्यकता को छोड़ दिया है, इसलिए यह "समस्या" अब कोई समस्या नहीं है।लेकिन आप सही हैं, सबसे अच्छा मार्ग निश्चित रूप से वसंत के कैश अमूर्तता में जा रहा है। धन्यवाद! –

+6

क्या हम सभी तरह की समस्याओं और अजीब व्यवहार का कारण नहीं बनते हैं, अगर हम स्प्रिंग कैश में इकाइयों को कैश करते हैं? –

+0

वसंत केवल "विधि दृश्यता और कैश एनोटेशन" के बाद कंक्रीट कक्षाओं (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html अनुच्छेद) को केवल एनोटेट करने की अनुशंसा करता है और मैं इसमें भागता हूं इंटरफ़ेस पर इसका उपयोग करने में यह त्रुटि: "वर्ग [वर्ग com.sun.proxy। $ Proxy180]" के CGLIB उप-वर्ग उत्पन्न नहीं कर सका। ऐसी स्थिति से निपटने के लिए अनुशंसित तरीका क्या है? (यह वसंत 4.1.7 के साथ है) – dave

7

आप जानते हैं कि हाइबरनेट QueryCache पर देकर आपके प्रश्नों कि बासी हो जाते हैं, जब बचत को अद्यतन करने, संस्थाओं है कि क्वेरी परिणाम प्रभावित को हटाने अमान्य के लिए जिम्मेदार हैं करने की आवश्यकता है (क्या ओलिवर CacheEvict की स्थापना करके कर रही है बचाने पर) - जो मुझे लगता है कि दर्द हो सकता है- या कम से कम आपको खाते में ध्यान रखना होगा और इसे अनदेखा करना होगा यदि यह वास्तव में आपके परिदृश्य के लिए कोई समस्या नहीं है।

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