USER
надо сделать, чтобы все методы из кэша брали
@Remote(PropertyService.class)
@Singleton
public class PropertyServiceImpl implements PropertyService {
private static final Logger LOGGER = LoggerFactory.getLogger(PropertyServiceImpl.class);
@Inject
private PropertyRepository propertyRepository;
private Map<NcsPropertyKey, NcsProperty> properties = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
final Map<NcsPropertyKey, NcsProperty> propertiesNew = new ConcurrentHashMap<>();
for (NcsProperty property: propertyRepository.findAll()) {
NcsPropertyKey key = new NcsPropertyKey(property.getModule(), property.getKey());
propertiesNew.put(key, property);
}
this.properties = propertiesNew;
LOGGER.info("[init] properties.size() = {}", properties.size());
}
/*
* (non-Javadoc)
*
* @see PropertyService#saveProperty(com.ncs.utils.model.NcsProperty)
*/
@Override
public NcsProperty saveProperty(NcsProperty property) {
return propertyRepository.save(property);
}
/*
* (non-Javadoc)
*
* @see PropertyService#getProperty(String, String)
*/
@Override
@Lock(READ)
public NcsProperty getProperty(String module, String key) {
return properties.get(new NcsPropertyKey(module, key));
}
@Override
@Lock(READ)
public NcsProperty getProperty(String module, String key, String defaultValue) {
NcsProperty ncsProperty = getProperty(module, key);
if (ncsProperty == null && defaultValue != null) {
ncsProperty = new NcsProperty();
ncsProperty.setModule(module);
ncsProperty.setKey(key);
ncsProperty.setValue(defaultValue);
}
return ncsProperty;
}
/*
* (non-Javadoc)
*
* @see PropertyService#getAll(org.springframework.data.domain.Pageable, com.ncs.utils.model.filter.NcsPropertyFilter)
*/
@Override
@Lock(READ)
public Page<NcsProperty> getAll(Pageable pager, NcsPropertyFilter filter) {
return propertyRepository.findAll(PropertySpecification.buildFilterSpecification(filter), pager);
}
/*
* (non-Javadoc)
*
* @see PropertyService#get(Long)
*/
@Override
@Lock(READ)
public NcsProperty get(Long id) {
return propertyRepository.findOne(id);
}
/*
* (non-Javadoc)
*
* @see PropertyService#save(com.ncs.utils.model.NcsProperty)
*/
@Override
public void save(NcsProperty property) {
// Update cache
properties.put(new NcsPropertyKey(property.getModule(), property.getKey()), property);
// Update repo
propertyRepository.save(property);
}
/*
* (non-Javadoc)
*
* @see PropertyService#delete(Long)
*/
@Override
public void delete(Long id) {
// Remove from cache
NcsProperty property = propertyRepository.findOne(id);
if (property != null) {
properties.remove(new NcsPropertyKey(property.getModule(), property.getKey()));
}
// Remove from repo
propertyRepository.delete(id);
}
@Override
@Lock(READ)
public List<String> getAllModules() {
List<String> moduleList = new ArrayList<>();
moduleList.add(ANY_VALUE);
moduleList.addAll(propertyRepository.findAll(PropertySpecification.buildFilterSpecification(new NcsPropertyFilter()))
.stream().map(NcsProperty::getModule).distinct().sorted().collect(Collectors.toList()));
return moduleList;
}
@Override
@Lock(READ)
public List<String> getAllKeys() {
List<String> keyList = new ArrayList<>();
keyList.add(ANY_VALUE);
keyList.addAll(propertyRepository.findAll(PropertySpecification.buildFilterSpecification(new NcsPropertyFilter()))
.stream().map(NcsProperty::getKey).distinct().sorted().collect(Collectors.toList()));
return keyList;
}
ASSISTANT
Чтобы реализовать кэширование для всех методов в вашем классе `PropertyServiceImpl`, необходимо убедиться, что данные читаются из кэша, когда это возможно, а только в случае отсутствия в кэше - извлекаются из базы данных.
Вот шаги, которые вам нужно выполнить, чтобы гарантировать, что все методы, которые запрашивают свойства, используют кэш, а также как обновить кэш при изменениях в базе данных.
### 1. Обновление методов для использования кэша
#### Метод `getProperty`
Исходный метод `getProperty` уже правильно обращается к кэшу. Однако, в зависимости от вашей бизнес-логики, вы могли бы рассмотреть вариант добавления доступа к данным из базы данных при отсутствии в кэше:
```java
@Override
@Lock(READ)
public NcsProperty getProperty(String module, String key) {
NcsProperty property = properties.get(new NcsPropertyKey(module, key));
if (property == null) {
property = propertyRepository.findByModuleAndKey(module, key); // Здесь делаем запрос в БД, если не нашли в кэше
if (property != null) {
// Если нашли в БД, обновляем кэш
properties.put(new NcsPropertyKey(module, key), property);
}
}
return property;
}
```
### 2. Обновление кэша после изменений
Не забудьте обновлять кэш для всех методов, которые изменяют состояние или читают его. Например, в методах `save`, `delete` и в некоторых других, нужно обновлять кэш, если данные обновлены.
```java
@Override
public void save(NcsProperty property) {
// Обновление кэша
properties.put(new NcsPropertyKey(property.getModule(), property.getKey()), property);
// Сохранение в репозитории
propertyRepository.save(property);
}
```
### 3. Обновление других методов
#### Метод `getAll`
Для метода `getAll` может не иметь смысла кэшировать в том же формате, что и другие методы, так как он возвращает список свойств. Вы можете рассмотреть возможность кэширования если у вас есть определенный набор фильтров и у вас есть отфильтрованные значения, которые задействуют эту логику.
Если кэширование здесь не требуется, можно оставить реализацию с вызовом репозитория:
```java
@Override
@Lock(READ)
public Page<NcsProperty> getAll(Pageable pager, NcsPropertyFilter filter) {
return propertyRepository.findAll(PropertySpecification.buildFilterSpecification(filter), pager);
}
```
#### Метод `getAllModules` и `getAllKeys`
Для методов `getAllModules` и `getAllKeys` также, скорее всего, имеется смысл напрямую обращаться к базе данных, так как они возвращают уникальные значения модулей и ключей. Однако, если вы хотите кэшировать их результаты, вы можете сохранить их в отдельном кэше:
```java
@Override
@Lock(READ)
public List<String> getAllModules() {
List<String> moduleList = new ArrayList<>(properties.values().stream()
.map(NcsProperty::getModule)
.distinct()
.collect(Collectors.toList()));
moduleList.add(0, ANY_VALUE); // Добавление ANY_VALUE
return moduleList;
}
@Override
@Lock(READ)
public List<String> getAllKeys() {
List<String> keyList = new ArrayList<>(properties.values().stream()
.map(NcsProperty::getKey)
.distinct()
.collect(Collectors.toList()));
keyList.add(0, ANY_VALUE); // Добавление ANY_VALUE
return keyList;
}
```
### 4. Инициирование кэша
Если кэш уже заполнен, а вы хотите его очистить, вы можете создать метод, который будет это делать:
```java
public void clearCache() {
properties.clear();
init(); // Перезагрузить кэш из БД
}
```
### 5. Уведомление об изменениях
Если используется обменник для уведомлений, измените методы `save` и `delete`, чтобы сбрасывать кэш или обновлять сырье, когда данные меняются.
### Заключение
Итак, теперь у вас есть четкое направление, как организовать использование кэша во всех методах вашего `PropertyServiceImpl`. Главное - всегда проверять кэш на наличие нужных данных и при необходимости делать запросы к базе данных, обновляя кэш, если данные были извлечены оттуда.