2013-02-21 2 views
4

Я использую запрос EclipseLink в Результаты кэша:Как очистить результаты запроса EclipseLink Cache от перехватчика CDI?

@NamedQuery(name = "User.findAll", 
    query = "SELECT s FROM ...", 
    hints= { 
      @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE, value=HintValues.TRUE) 
      ... 

и я сначала вручную очищается кэш с помощью лица без боб под названием «CacheManager», который имел следующий метод:

public void invalidateCacheForQuery(String namedQueryName) { 
    log.info("CacheManagerService: clearing cache for named query " + namedQueryName); 
    ((JpaCache) em.getEntityManagerFactory().getCache()) 
     .clearQueryCache(namedQueryName); 
} 

Я d вызывать этот метод всякий раз, когда есть модификация (добавление/удаление), которая могла бы привести к тому, что результаты запроса устарели. Вызов был сделан непосредственно после модификации, например.

em.merge(u); 
cacheMan.invalidateCacheForQuery("..."); // for each cached query 

(Я немного сокращаю углы, это сущность того, что я делаю).

Вышеупомянутое решение сработало хорошо - у меня есть тесты JUnit, которые не сработают, если кеш не очищен, и они не сбой, если присутствуют вышеуказанные «invalidateCacheForQuery» вызовы (и не сработают, если они не являются).

Тогда я попытался сделать свою жизнь проще, определяя перехватчик:

@EJB CacheManager cacheMan; 

@AroundInvoke 
public Object clearQueryCacheAfterwards(InvocationContext ctx) 
     throws Exception { 

    // this does something like em.persist that might make cached query results 
    // invalid: 
    final Object result = ctx.proceed(); 

    // hera are calls cacheMan.invalidateCacheForQuery for all of the relevant named 
    // queries. Yes, this is done after ctx.proceed(). 

    return result; 
} 

Примечания: Я сохранил код выше лаконично: Перехватчик аннотацию принял объект класса в качестве параметра, и я использовал объект класса чтобы найти все его имена NamedQueries, у которых был QueryHint, указывающий, что они были кэшированы. Это просто, чтобы объяснить, как я нашел, что именовал запросы для очистки.

Подход перехватчика не работает, и я понятия не имею, почему. Я знаю, что метод invalidateCacheForQuery(String namedQueryName) вызывается также с использованием подхода Interceptor (с именами имен с правом имени), поскольку я получаю правильные сообщения журнала. Я также получаю сообщения журнала из перехватчика. Механизм перехватчика работает, например. это не простая проблема, как определение отсутствует в beans.xml. Однако я знаю, что очистка кеша не работает, потому что мои тесты JUnit терпят неудачу так же, как они терпят неудачу, если я вообще не очищаю кеш.

Глядя на бревне, эти последовательные линии заставляют меня убедиться, что перехватчик делает то, что он должен:

ClearQueryCacheInterceptor: clearing query cache for named query User.findAll 
CacheManagerService: clearing cache for named query User.findAll 

Я также попытался использовать @PersistenceContext(unitName="...") EntiytyManager em; в перехватчик и очистить кэш через который без использования CacheManager EJB ,

Итак, чтобы пояснить подробное объяснение: у меня есть два подхода, вызывающих тот же метод, который делает недействительным кеш результатов запроса EclipseLink. Я проверил через протоколирование, что оба подхода управляют вызовом этого метода с теми же параметрами (имена NamedQuery). Встраиваемый «после em.persist()» способ работает, но делать практически то же самое в перехватчике нет. Мне кажется, что я очищаю другой экземпляр кэша EclipseLink с перехватчиком, но я не знаю, как это возможно.

+0

Является ли ваш EJB без гражданства или состояния? – LightGuard

+0

Все без гражданства. –

+0

Возможно, вы очищаете другой экземпляр сеансового компонента. – LightGuard

ответ

1

Ваша проблема заключается в том, что вы используете два разных типа PersistenceContext при использовании подхода Interceptor.

Похоже, что ваша конфигурация перехватчика работает на уровне Entity, который не передает PersistenceContext вашего контейнера EJB. Попробуйте переместить перехватчик на уровень обслуживания (примените его к EJB, которые сохраняют/изменяют данные). Это не так автоматически, как вы пытаетесь сделать, но должно работать.

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