Я использую запрос 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 с перехватчиком, но я не знаю, как это возможно.
Является ли ваш EJB без гражданства или состояния? – LightGuard
Все без гражданства. –
Возможно, вы очищаете другой экземпляр сеансового компонента. – LightGuard