إبطال ذاكرة التخزين المؤقت لـ Hibernate 2nd عندما تقوم عملية أخرى بتعديل قاعدة البيانات

StackOverflow https://stackoverflow.com/questions/1603846

سؤال

لدينا تطبيق يستخدم التخزين المؤقت للمستوى الثاني من Hibernate لتجنب ضربات قاعدة البيانات.

كنت أتساءل عما إذا كانت هناك طريقة سهلة لإبطال ذاكرة التخزين المؤقت لـ Java Application من المستوى الثاني عندما تكون عملية خارجية مثل مسؤول MySQL متصلاً مباشرة لتعديل قاعدة البيانات (تحديث/إدراج/حذف).

نحن نستخدم ehcache كما تنفيذ ذاكرة التخزين المؤقت من المستوى الثاني.

نحن نستخدم مزيجًا من cache (use = cacheconcurrencystrategy.read_write) و cache (use = cacheconcurrencystrategy.nastrict_read_write) ، وليس لدينا التحكم في التزامن المتفائل باستخدام الطوابع الزمنية على كل كيان.

يحتوي SessionFactory على طرق لإدارة ذاكرة التخزين المؤقت للمستوى الثاني: - إدارة ذاكرة التخزين المؤقت

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 ، فلا يوجد مكان رئيسي لنا "بشكل موثوق" (على سبيل المثال لا توجد خطوات يدوية) أضف ذلك إلى القائمة.

// 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);
   }
}

لا توجد طريقة حقيقية لتخزين ذاكرة التخزين المؤقت للمستوى الثاني من Hibernate أن يعرف أن الكيان تم تغييره في DB ما لم يستفسر عن هذا الكيان (وهو ما تحميك من ذاكرة التخزين المؤقت). لذلك ربما كحل ، يمكننا ببساطة تسمية بعض الطرق لإجبار ذاكرة التخزين المؤقت من المستوى الثاني على إخلاء كل شيء (مرة أخرى بسبب عدم وجود قفل والتحكم في التزامن تخاطر به في معاملات التقدم من "القراءة" أو تحديث البيانات التي لا معنى لها).

هل كانت مفيدة؟

المحلول

مرتكز على chssply76 التعليقات فيما يلي طريقة تطرد جميع الكيانات من ذاكرة التخزين المؤقت من المستوى الثاني (يمكننا تعريض هذه الطريقة للمساولين من خلال 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);
    }
}

نصائح أخرى

SessionFactory لديه الكثير evict() الطرق على وجه التحديد لهذا الغرض:

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

يوفر كل من Hibernate و JPA الآن الوصول المباشر إلى ذاكرة التخزين المؤقت من المستوى الثاني:

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

كنت أبحث عن كيفية إبطال جميع ذاكرة التخزين المؤقت للإسبات ووجدت هذا المقتطف المفيد:

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

آمل أن يساعد ذلك على شخص آخر.

يمكنك محاولة القيام بذلك:

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;
}

اتمني ان يكون مفيدا.

شيء واحد يجب مراعاته عند استخدام ذاكرة التخزين المؤقت الموزعة هو أن QueryCache محلي ، وإزالةها على عقدة واحدة ، لا يطردها من غيرها. هناك مسألة أخرى - إخلاء منطقة الكيان دون إخلاء منطقة الاستعلام سوف تتسبب في اختيارات N+1 ، عند محاولة استرداد التاريخ من ذاكرة التخزين المؤقت للاستعلام. قراءات جيدة حول هذا الموضوع هنا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top