2016-10-03 7 views
0

Короче говоря, когда @CacheEvict вызывается по методу, и если ключ для записи не найден, Gemfire бросает EntryNotFoundException.Gemfire EntryNotFoundException для @CacheEvict

Теперь подробно,

У меня есть класс

class Person { 

String mobile; 
int dept; 
String name; 

} 

У меня есть две области кэша, определенные как personRegion и personByDeptRegion и службы, как показано ниже

@Service 
class PersonServiceImpl { 

    @Cacheable(value = "personRegion") 
    public Person findByMobile(String mobile) { 

     return personRepository.findByMobile(mobile); 

    } 


    @Cacheable(value = "personByDeptRegion") 
    public List<Person> findByDept(int deptCode) { 

     return personRepository.findByDept(deptCode); 

    } 


    @Caching(
     evict = { @CacheEvict(value = "personByDeptRegion", key="#p0.dept"}, 
     put = { @CachePut(value = "personRegion",key = "#p0.mobile")} 

    ) 
    public Person updatePerson(Person p1) { 

     return personRepository.save(p1); 

    } 

} 

Когда есть вызовите updatePerson, и если в personByDeptRegion нет записей, это вызовет исключение, которое EntryNotFoundException для ключа 1 (или что-то еще является кодом dept) , Существует очень хороший шанс, что этот метод будет вызван до вызова методов @Cacheable и будет избегать этого исключения. Можно ли каким-либо образом изменить поведение Gemfire, чтобы изящно вернуться, когда ключ не существует для данного региона? В качестве альтернативы, я также хочу знать, есть ли более эффективная реализация описанного выше сценария с использованием Gemfire в качестве кеша.

Spring Data Gemfire: 1.7.4

Gemfire Версия: v8.2.1

Примечание: Приведенный выше код только для представления цели и у меня есть несколько служб с той же проблемой в реальном проекте.

+0

Wow! Вы должны рассмотреть возможность обновления вашей версии SDG! 1.3.5.RELEASE? o.O Вы понимаете, что «1.8.4.RELEASE» - самая последняя версия (на основе GF 8.2.0). 1.7.6.RELEASE - поддерживаемая в настоящее время версия обслуживания (на основе GF 8.1.0). И SDG 1.9 в настоящее время находится в разработке, с уже имеющимся 1,9 M1 и 1,9 GA запланировано на 12 декабря. Вы можете оставаться в курсе, просматривая страницу проекта SDG (http://projects.spring.io/spring-data-gemfire/) ... –

+0

... а также взгляните на страницу Wiki-страницы совместимости проекта (https : //github.com/spring-projects/spring-data-gemfire/wiki/Spring-Data-GemFire-to-GemFire-Version-Compatibility). Кроме того, вы можете просмотреть сведения о выпуске на странице Wiki Wiki (https://github.com/spring-projects/spring-data-commons/wiki); см. столбец Nav справа. Текущие выпуски Gosling (SDG 1.7.6.RELEASE) & Hopper (SDG 1.8.4.RELEASE). Ингаллс (https://github.com/spring-projects/spring-data-commons/wiki/Release-Train-Ingalls) подходит и подходит. –

+0

Сказав это ... Я немного поработаю с ответом на ваш вопрос. –

ответ

1

Во-первых, я рекомендую использовать Spring's Кэширование аннотаций на ваше приложение @Service компонентов. Слишком часто разработчики разрешают кэширование в своих хранилищах, что, по моему мнению, является плохой формой, особенно если сложные бизнес-правила (или даже дополнительный ввод-вывод, например вызов веб-службы из компонента службы) задействованы до или после взаимодействия (репозитория) , особенно в тех случаях, когда поведение кеширования не должно затрагиваться (или определяется).

Я также думаю, что ваше кэширование UC (обновление одного кэша (personRegion), а недействительность другие (personByDeptRegion) на обновлении хранилища данных), следуя CachePut с CacheEvict кажется разумным мне. Хотя, я хотел бы отметить, что, казалось бы, предполагаемое использование @Caching аннотации объединить несколько аннотаций Кэширования из же типа (например, кратного @CacheEvict или нескольких @CachePut), как описано в ядре Spring FrameworkReference Guide. Тем не менее, ничего не мешает вашему предполагаемому использованию.

Я создал аналогичный класс тестов here, смоделированный после вашего примера выше, чтобы проверить проблему. Действительно jonDoeUpdateSuccessful тест не удается (с GemFire ​​EntryNotFoundException, как показано ниже), так как ни один народ в Department «R & D» были ранее сохраненным в «DepartmentPeople» GemFire ​​области до обновления, в отличие от janeDoeUpdateSuccessful теста, что приводит к кэш для заполнения до обновления (даже если запись не имеет значений, что не имеет значения).

com.gemstone.gemfire.cache.EntryNotFoundException: RESEARCH_DEVELOPMENT 
    at com.gemstone.gemfire.internal.cache.AbstractRegionMap.destroy(AbstractRegionMap.java:1435) 

ПРИМЕЧАНИЕ: Мой тест использует GemFire ​​и как «кэш поставщика» и система записи (СНП).

Проблема действительно заключается в использовании SDG о Region.destroy(key) в GemfireCache.evict(key) реализации, а не, и, возможно, более уместно, Region.remove(key).

GemfireCache.evict(key) был выполнен с Region.destroy(key) с момента создания. Однако Region.remove(key) не был представлен до GemFire ​​v5.0. Тем не менее, я не вижу различимой разницы между Region.destroy(key) и Region.remove(key), кроме EntryNotFoundException, брошенных Region.destroy(key). По сути, они оба уничтожают локальную запись (как ключ, так и значение), а также распределяют операцию с другими кэшами в кластере (при этом используется не LOCALScope).

Итак, я подал SGF-539 изменить SDG вызвать Region.remove(key) в GemfireCache.evict(key), а не Region.destroy(key).

Что касается обходного пути, ну там в основном только две вещи, которые вы можете сделать:

  1. Реструктурировать ваш код и ваше использование @CacheEvict аннотацию, и/или ... использование
  2. Сделать из condition на @CacheEvict.

К сожалению, что condition не может быть определен с помощью типа класса, что-то похожее на SpringCondition (в дополнение к SPEL), но этот интерфейс предназначен для другой цели и @CacheEvict, condition атрибут делает не допускайте тип класса.

На данный момент у меня нет хорошего примера, как это может работать, поэтому я продвигаюсь вперед по SGF-539.

Вы можете следовать этому билету для получения более подробной информации и прогресса.

Извините за неудобства.

-John

+0

@Sandheep - У меня отличные новости ... Я понял, что обходное решение для вас до тех пор, пока не решит SGF-539.См. Мой пример тестового примера обновления (https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CacheEvictionWithGemFireIntegrationTest.java#L146-L167) для получения дополнительной информации. , –

+0

Примечание. Ключом к «обходному пути» является это ... https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CacheEvictionWithGemFireIntegrationTest.java # L157 (точно изменение SDG, которое нужно сделать) ... ;-) –

+0

Excellcent John :). Большое вам спасибо за создание билета и особенно за немедленное обходное решение. Был застрял в этом. Проверите обходное решение и сообщите об этом. – Sandheep