2009-10-21 12 views
22

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

मैं सोच रहा था कि क्या जावा अनुप्रयोग के हाइबरनेट द्वितीय स्तर के कैश को अमान्य करने का कोई आसान तरीका है जब एक बाहरी प्रक्रिया जैसे कि MySQL व्यवस्थापक डेटाबेस (अद्यतन/सम्मिलित/हटाएं) को संशोधित करने के लिए सीधे कनेक्ट होता है।

हम अपने दूसरे स्तर के कैश कार्यान्वयन के रूप में EHCache का उपयोग कर रहे हैं।

हम @Cache (उपयोग = CacheConcurrencyStrategy.READ_WRITE) और @Cache (उपयोग = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) के मिश्रण का इस्तेमाल, और हम आशावादी संगामिति नियंत्रण प्रत्येक इकाई के टाइमस्टैम्प का उपयोग करते हुए सक्षम नहीं है। हमारे लिए "मज़बूती से" (उदाहरण के लिए कोई मैनुअल के लिए Managing the Caches

sessionFactory.evict(Cat.class, catId); //evict a particular Cat 
sessionFactory.evict(Cat.class); //evict all Cats 
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens 
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections 

लेकिन क्योंकि हम @Cache साथ अलग-अलग इकाई वर्गों व्याख्या, वहाँ कोई केंद्रीय स्थान है - :

SessionFactory 2 स्तर कैश का प्रबंधन करने के तरीकों में शामिल है कदम) सूची में जोड़ें।

// Easy to forget to update this to properly evict the class 
public static final Class[] cachedEntityClasses = {Cat.class, Dog.class, Monkey.class} 

public void clear2ndLevelCache() { 
    SessionFactory sessionFactory = ... //Retrieve SessionFactory 

    for (Class entityClass : cachedEntityClasses) { 
     sessionFactory.evict(entityClass); 
    } 
} 

हाइबरनेट के 2 स्तर कैश के लिए कोई असली तरीका पता चला है कि एक इकाई डीबी में बदल जब तक यह क्वेरी जिनका इकाई (जो क्या कैश आप से सुरक्षा कर रहा है) नहीं है। तो हो सकता है कि एक समाधान के रूप में हम केवल दूसरे स्तर के कैश को सब कुछ बेदखल करने के लिए मजबूर करने के लिए कुछ विधि कह सकते हैं (फिर से लॉकिंग और समवर्ती नियंत्रण की कमी के कारण आपको "पढ़ने" या स्टाइल डेटा अपडेट करने से प्रगति लेनदेन में जोखिम होता है)।

उत्तर

14

ChssPly76's टिप्पणियां के आधार पर यहां एक विधि है कि 2 स्तर कैश से सभी संस्थाओं evicts है (हम JMX या अन्य व्यवस्थापक के माध्यम से व्यवस्थापक के लिए इस विधि का पर्दाफाश कर सकते हैं उपकरण):

/** 
* Evicts all second level cache hibernate entites. This is generally only 
* needed when an external application modifies the game databaase. 
*/ 
public void evict2ndLevelCache() { 
    try { 
     Map<String, ClassMetadata> classesMetadata = sessionFactory.getAllClassMetadata(); 
     for (String entityName : classesMetadata.keySet()) { 
      logger.info("Evicting Entity from 2nd level cache: " + entityName); 
      sessionFactory.evictEntity(entityName); 
     } 
    } catch (Exception e) { 
     logger.logp(Level.SEVERE, "SessionController", "evict2ndLevelCache", "Error evicting 2nd level hibernate cache entities: ", e); 
    } 
} 
+0

मैं नीचे विधि कॉल करके दूसरे स्तर के कैश से कैश डेटा साफ़ करना चाहता हूं: - sessionFactory.getCache()। EvictEntityRegions(); मैं बस जानना चाहता हूं, क्या ऐसा करने में कोई हानि है? उदाहरण के लिए: - लेनदेन के बीच में कैश साफ़ करने का प्रयास करने पर क्या होगा? –

11

SessionFactory ठीक उस उद्देश्य के लिए evict() तरीकों के बहुत सारे है:

sessionFactory.evict(MyEntity.class); // remove all MyEntity instances 
sessionFactory.evict(MyEntity.class, new Long(1)); // remove a particular MyEntity instances 
+0

क्या दूसरे स्तर के कैश से @ कैश के साथ एनोटेटेड सभी कक्षाओं के सभी उदाहरणों को बेदखल करने का एक विश्वसनीय तरीका है। हम आम तौर पर द्वितीय स्तर के कैश को सक्षम करने के लिए कक्षाओं को एनोटेट करते हैं और इसलिए दूसरी स्तर कैश में कोई नई इकाई जोड़े जाने पर कोड को अपडेट करने के लिए वास्तव में एक केंद्रीय स्थान नहीं है। – Dougnukem

+1

ईमानदार होने के लिए, ** ** ** सभी ** उदाहरणों को चरम मामले की तरह लग रहा है। इसे अक्सर पर्याप्त करें और आप बिना किसी कैश के प्रदर्शन के साथ खराब प्रदर्शन कर सकते हैं। उस ने कहा, आप 'getAllClassMetadata()' विधि (नाम लौटाए गए मानचित्र की चाबियाँ हैं) के माध्यम से सभी इकाइयों के नाम प्राप्त कर सकते हैं और प्रत्येक के लिए 'evictEntity()' पर कॉल कर सकते हैं। – ChssPly76

+0

यह केवल एक बेहद दुर्लभ अवसर है जब हमें सर्वर के उत्पादन के बिना "HOTFIX" उत्पादन करने की आवश्यकता होती है और हमारे मौजूदा ग्राहक सेवा व्यवस्थापक उपकरण ऐसा नहीं कर सकते हैं (और हम कुछ व्यवस्थापक कमांड का पर्दाफाश नहीं करेंगे आपको कुछ मनमानी एसक्यूएल निष्पादित करने देता है)। फिर फिर एक बाहरी व्यवस्थापक को एसक्यूएल निष्पादित करने की इजाजत देकर हम सभी लेनदेन लेखा परीक्षा और लॉगिंग खो देते हैं। – Dougnukem

8

दोनों हाइबरनेट और जेपीए अब अंतर्निहित 2 स्तर कैश के लिए सीधी पहुँच प्रदान करते हैं:

sessionFactory.getCache().evict(..); 
entityManager.getCache().evict(..) 
2

मैं सभी हाइबरनेट कैश रद्द करने के लिए कैसे खोज रहा था और मैं इस उपयोगी स्निपेट नहीं मिली:

sessionFactory.getCache().evictQueryRegions(); 
sessionFactory.getCache().evictDefaultQueryRegion(); 
sessionFactory.getCache().evictCollectionRegions(); 
sessionFactory.getCache().evictEntityRegions(); 

आशा है कि इसे किसी और को मदद मिलती है।

1

ऐसा करने की कोशिश कर सकते हैं:

private EntityManager em; 

public void clear2ndLevelHibernateCache() { 
    Session s = (Session) em.getDelegate(); 
    SessionFactory sf = s.getSessionFactory(); 

    sf.getCache().evictQueryRegions(); 
    sf.getCache().evictDefaultQueryRegion(); 
    sf.getCache().evictCollectionRegions(); 
    sf.getCache().evictEntityRegions(); 

    return; 
} 

मुझे आशा है कि यह मदद करता है।

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