2009-08-19 2 views
0

В своем превосходном сообщении в блоге «Hibernate query cache considered harmful?» Алекс Миллер (Terracotta Inc.) объясняет, почему использование кеша запросов может быть вредным для латентности и масштабируемости.Извлечь все Foo из кэша второго уровня Hibernate без кэша запросов?

Мой вопрос: возможно ли написать метод «получить все» DAO для определенного типа объекта домена, который использует кеш второго уровня без кэша запросов?

Моя обычная форма коды для такого способа включает кэш запросов, например:

public List<Foo> getAllFoo() 
{ 
    return (List<Foo>) getHibernateTemplate().execute(new HibernateCallback() 
    { 
     public Object doInHibernate(Session session) 
     { 
      Query q = session.createQuery("from Foo"); 
      // Cache the results in the query cache. 
      q.setCacheable(true); 
      return q.list(); 
     } 
    }); 
} 

Моей единственной расплывчатую мысль поддержание кэшированной совокупности всех Foo на каком-либо объекте синглтона домена (который также кэшируется) , Есть ли более элегантный способ?

+0

ли вы имеете в виду получить все из базы данных или все, что в настоящее время в кеше? Если это первый, Hibernate будет обрабатывать его для вас с обычным запросом «из таблицы». Если это последний, вы можете добраться до самого кеша и просто перебрать его. –

+0

Последний (извините, если это непонятно в заголовке вопроса). Как я могу «добраться до самого кеша и просто перебирать его»? –

ответ

1

Если вы используете EhCacheProvider, то вы хотите получить доступ к переменной-члену CacheManager. К сожалению, он не имеет общих методов доступа, поэтому я создал свою собственную копию EhCacheProvider, которая использовала статический для CacheManager статический общедоступный метод для его возврата. Я предполагаю, что вы могли бы обращаться с другими поставщиками кэшей одинаково или просто реализовывать интерфейс CacheProvider.

Как только у вас есть CacheManager, вы получите кэш для имени домена (класса) с помощью cacheManager.getCache (имя класса). Это возвращает кэш, который можно выполнить с помощью cache.getKeys(). Каждый ключ - это CacheKey, у которого есть идентификатор объекта, поэтому вы можете использовать cache.get (key) для возврата фактического объекта.

Другой вариант, если вы не возражаете, минуя некоторую безопасность Java и в зависимости от конкретной реализации Hibernate что-то вроде (обработка исключений опущена):

EhCacheProvider cp = (EhCacheProvider)((SessionFactoryImpl)session.getSessionFactory()).getSettings().getCacheProvider() 
    Field f = EhCacheProvider.class.getDeclaredField("manager"); 
    f.setAccessible(true); 
    CacheManager cm = (CacheManager)f.get(cp); 
    Cache c = cm.get(Entity.class); 
+0

Интересно. Имея доступ к кешу прямо так, я должен отвечать за проверку того, был ли кеш недействителен (например, из-за вставленной другой записи) и обновил кеш, если он есть? Или я даже должен сам позаботиться о недействительности, проверив кеш timestamps? –

+0

Я так не думаю. Вызов метода Cache.get аналогичен выполнению обычной загрузки Hibernate, которая попадает в кеш, поэтому он проверяет дату истечения срока действия. Все, что делает этот код, - это получить список ключей в кеше досрочно и не попасть в базу данных, если он не находится в кеше. Вы хотите выполнить нулевую проверку после получения в случае, если она истекло между временем, когда вы получили список ключей и время, когда вы получили этот элемент. –

Смежные вопросы