2010-05-11 13 views
37

मैं अपने डेटाबेस से डेटा प्राप्त करने के लिए जेपीए (eclipselink) का उपयोग करना चाहता हूं। डेटाबेस को कई अन्य स्रोतों द्वारा बदला जाता है और इसलिए मैं निष्पादित किए गए प्रत्येक खोज के लिए डेटाबेस पर वापस जाना चाहता हूं। मैंने कैश को अक्षम करने पर कई पोस्ट पढ़ी हैं लेकिन ऐसा लगता है कि यह काम नहीं कर रहा है। कोई विचार?जेपीए (eclipselink) में कैशिंग अक्षम करें

मैं निम्नलिखित कोड निष्पादित करने के लिए कोशिश कर रहा हूँ:

 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("default"); 
     EntityManager em = entityManagerFactory.createEntityManager(); 

     MyLocation one = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0); 

     MyLocation two = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0);  

     System.out.println(one==two); 

एक == दो सच है, जबकि मैं यह गलत होना चाहता हूँ।

मैं प्रत्येक जोड़ने की कोशिश की है/मेरे सभी persistence.xml के लिए निम्न

<property name="eclipselink.cache.shared.default" value="false"/> 
<property name="eclipselink.cache.size.default" value="0"/> 
<property name="eclipselink.cache.type.default" value="None"/> 

मैं भी इकाई में ही @Cache एनोटेशन जोड़ने की कोशिश की है: कुछ

@Cache(
    type=CacheType.NONE, // Cache nothing 
    expiry=0, 
    alwaysRefresh=true 
) 

मैं गलत समझ रहा हूँ ?

+0

जेम्स द्वारा डेटाबेस में जाने के लिए प्रत्येक क्वेरी मजबूर कर सकते हैं, कैशिंग बंद किया गया था (<संपत्ति नाम = "eclipselink.cache.shared.default "value =" false "/> ) जब आपने इसका परीक्षण किया? – Justin

+0

क्षमा करें बस यह देखा, हाँ कैशिंग बंद था। मुझे अभी भी यह समस्या है और मैं समाधान के करीब नहीं हूं। – James

उत्तर

34

यह व्यवहार सही है, अन्यथा यदि आप ऑब्जेक्ट को बदलते हैं और अलग-अलग मानों के साथ दो ऑब्जेक्ट करते हैं तो उन्हें जारी रखने में आपको समस्या होगी। क्या हो रहा है कि वस्तु को लोड करने के लिए कॉल दो कॉल को पहली कॉल में लोड किया गया है। उन्हें एक ही वस्तु को इंगित करना चाहिए क्योंकि वे एक ही वस्तु हैं। यह सुनिश्चित करता है कि गंदे डेटा को लिखा नहीं जा सकता है।

यदि आप दो कॉल के बीच em.clear() को कॉल करते हैं, तो इकाई को अलग किया जाना चाहिए आपकी जांच झूठी वापसी होगी। हालांकि ऐसा करने की कोई ज़रूरत नहीं है, ग्रहण लिंक वास्तव में आपके डेटा को नवीनतम अपडेट कर रहा है जो मुझे लगता है कि आप जो चाहते हैं वह अक्सर बदलता है।

एक तरफ ध्यान दें यदि आप जेपीए का उपयोग करके इस डेटा को अपडेट करना चाहते हैं तो आपको इकाई पर pessimistic locks प्राप्त करने की आवश्यकता होगी ताकि अंतर्निहित डेटा डीबी में नहीं बदला जा सके।

आप क्वेरी कैश को अक्षम करने के रूप में अच्छी तरह अपने कैश विकल्प सिर्फ खेलने नहीं क्वेरी कैश से वस्तु संचय को निकालने थे की आवश्यकता होगी, यही वजह है कि आप नए परिणाम नहीं मिल रहा है:

अपने कोड में:

em.createNamedQuery("MyLocation.findMyLoc").setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache).getResultList().get(0); 

या persistence.xml में:

<property name="eclipselink.query-results-cache" value="false"/> 
+0

इससे आपको धन्यवाद मिलती है। मुझे निराशावादी ताले देखना होगा क्योंकि डेटा बदल जाएगा। फिर यदि मैं एक थ्रेड जोड़ता हूं।प्रश्नों के बीच नींद (10000) और उस समय डेटाबेस में MyLocation की एक विशेषता मैन्युअल रूप से बदलती है दो (और इसलिए एक) इस परिवर्तन को प्रतिबिंबित नहीं करती है? – James

+0

ने निराशावादी ताले के बारे में कुछ जानकारी के लिए एक लिंक जोड़ा – Justin

+0

मैंने कोड और persistence.xml में वर्णित परिवर्तन की कोशिश की है और अभी भी वह मूल्य नहीं मिला है जिसे मैंने सीधे बदला है। कोई विचार? – James

3

मैन्युअल वस्तु की विशेषताओं को संशोधित करने के लिए, उदाहरण के लिए MyLocation। उपर्युक्त चाल (CACHE_USAGE=CacheUsage.DoNotCheckCache, या eclipselink.query-results-cache=false) जैसा कि मैंने कोशिश की थी, काम नहीं कर रहा है।

तो मैंने eclipselink.refresh पर true पर एक और संकेत सेट करने का प्रयास किया। तो यह काम करता है। मेरा मतलब है कि मैन्युअल रूप से परिवर्तित गुण पुनर्प्राप्त हो जाते हैं।

तो जैसा कि मैं समझता हूं, उपर्युक्त चाल केवल यह सुनिश्चित करती है कि यह सही वस्तुओं को प्राप्त करे। हालांकि, अगर वस्तुओं को पहले से ही कैश किया गया है, तो eclipselink ऑब्जेक्ट्स की सामग्री की ताजगी की जांच किए बिना उन्हें वापस कर देता है। केवल जब संकेत eclipselink.refreshtrue पर सेट किया गया है, तो क्या इन ऑब्जेक्ट्स को नवीनतम विशेषता मानों को प्रतिबिंबित करने के लिए ताज़ा किया जाएगा।

+4

हवा आप इसे अपने persistence.xml में सेट करते हैं? अगर मैं इस संकेत को क्वेरी में जोड़ता हूं तो यह काम करता है। लेकिन अगर मैं इसे केवल अपने persistence.xml में परिभाषित करता हूं तो यह काम नहीं करता है। – Christian

22
final Query readQuery = this.entityManager.createQuery(selectQuery); 
readQuery.setParameter(paramA, valueA); 

// Update the JPA session cache with objects that the query returns. 
// Hence the entity objects in the returned collection always updated. 
readQuery.setHint(QueryHints.REFRESH, HintValues.TRUE); 

entityList = readQuery.getResultList(); 

यह मेरे लिए काम करता है।

+0

यह एक आश्चर्यजनक रूप से काम करता है – kebyang

+0

यह वही है जो केवल मेरे लिए काम करता है। –

10

देखें,

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

ही EntityManager जेपीए के लिए हमेशा कि एक == दो आवश्यकता है, इसलिए यह सही है, अपने कैशिंग विकल्प (इस एल 1 कैश, या लेन-देन संबंधी कैश, है कोई फर्क नहीं जो आपके लेनदेन अलगाव को लागू करता है और वस्तु पहचान को बनाए रखता है)।

क्वेरी को ताज़ा करने के लिए मजबूर करने के लिए (और आपके द्वारा किए गए किसी भी बदलाव को वापस लाएं) आप क्वेरी संकेत "eclipselink.refresh" = "true" का उपयोग कर सकते हैं। या शायद बेहतर, प्रत्येक क्वेरी/अनुरोध के लिए एक नया EntityManager का उपयोग करें, या अपने EntityManager पर स्पष्ट() को कॉल करें।

<property name="eclipselink.cache.shared.default" value="false"/> 

साझा कैश (एल 2 कैश) को अक्षम करने का सही तरीका है। कृपया अपनी सभी अन्य सेटिंग्स को हटा दें क्योंकि वे सही नहीं हैं, और समस्याएं पैदा कर सकते हैं।

EclipseLink डिफ़ॉल्ट रूप से क्वेरी कैश को बनाए रखता नहीं है, इसलिए उन सेटिंग्स का कोई प्रभाव नहीं पड़ेगा। कैशयूजेज भी सही नहीं है, इसका उपयोग न करें (यह स्मृति में पूछताछ के लिए है)।

@Cacheable(false) 

यहाँ एक उदाहरण है:

+1

ध्यान दें कि "eclipselink.refresh" = "true" EclipseLink के वर्तमान संस्करणों में buggy है (https://bugs.eclipse.org/bugs/show_bug.cgi?id=398074); यह भी ग्रहण-विशिष्ट है और जेपीए का हिस्सा नहीं है। तो जब भी आप ताजा डेटा चाहते हैं तो मैं केवल एक नया EntityManager प्राप्त करने की सलाह दूंगा - इस तरह यह जेपीए के साथ काम करना चाहिए। – sleske

+0

एक नया EntityManager प्राप्त करने से आपको सीधे डेटाबेस से ताज़ा वस्तु नहीं मिल जाएगी। कैश एक EntityManagerFactory स्तर पर काम करता है, जो आमतौर पर आवेदन का जीवन समय है। – OliBlogger

7

आप आप के साथ अपने डोमेन वस्तु पर टिप्पणी कर सकता है विक्रेता विशिष्ट प्राप्त किए बिना कैशिंग को अक्षम करना चाहते, तो

@Entity 
@Table(name="SomeEntity") 
@Cacheable(false) 
public class SomeEntity { 
    // ... 
} 
3

मैं जानता हूँ कि इस पोस्ट पुराने हो सकता है, लेकिन मैं उन लोगों के लिए लिख रहा हूं जिन्हें सहायता चाहिए। मैं इस समस्या थी और अंत में मैं इसे इस कोड द्वारा हल:

em.createNamedQuery("findAll").setHint(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS).getResultList(); 

यह वास्तव में अच्छी तरह से काम करता है। और हम BYPASS enum के जावाडोक में देख सकते हैं, यह लिखा गया है कि:

कैश बाईपास करें: सीधे डेटाबेस से डेटा प्राप्त करें।

मुझे नोटिस करना चाहिए कि मैं वेबलॉगिक 12 सी और टॉपलिंक का उपयोग जेपीए कार्यान्वयन के रूप में करता हूं।

+0

ऊपर उल्लिखित ताज़ा संकेत आपके लिए काम नहीं करता है? – cen

+0

मैंने कोशिश नहीं की, क्योंकि मैं कुछ प्रश्नों में जेपीए कैश को बाईपास करना चाहता था। – AliReza19330

1

डिफ़ॉल्ट स्तर कैश डिफ़ॉल्ट रूप से सक्षम है और आप इसे अक्षम नहीं कर सकते हैं। यानी आपकी persistence.xml फ़ाइल में कोई सेटिंग पहले स्तर कैश को अक्षम कर देगी।

आप केवल

entityManager.clear() 

फोन करके सभी इकाई प्रबंधक वस्तुओं बाहर साफ कर सकते हैं इस बाद के प्रश्नों (पहली बार) डेटाबेस के लिए जाना कर देगा और उसके बाद फिर से वस्तुओं कैश में जमा हो जाती है

आप सीधे मेरे जवाब देने के लिए अपनी टिप्पणी में बुला

query.setHint("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);