@Cacheable работает в контроллере, но не внутри службы

У меня эта странная проблема в Spring Boot, где @Cacheable работает в контроллере, но не внутри службы. Я вижу вызов GET в Redis, но не вызов PUT.

Это работает, так как он находится внутри контроллера

@RestController
@RequestMapping(value = "/places")
public class PlacesController {

    private AwesomeService awesomeService;

    @Autowired
    public PlacesController(AwesomeService awesomeService) {
        this.awesomeService = awesomeService;
    }

    @GetMapping(value = "/search")
    @Cacheable(value = "com.example.webservice.controller.PlacesController", key = "#query", unless = "#result != null")
    public Result search(@RequestParam(value = "query") String query) {
        return this.awesomeService.queryAutoComplete(query);
    }
}

Но @Cacheable не работает, когда я делаю это в Сервисе вот так

@Service
public class AwesomeApi {

    private final RestTemplate restTemplate = new RestTemplate();

    @Cacheable(value = "com.example.webservice.api.AwesomeApi", key = "#query", unless = "#result != null")
    public ApiResult queryAutoComplete(String query) {
        try {
            return restTemplate.getForObject(query, ApiResult.class);
        } catch (Throwable e) {
            return null;
        }
    }
}

Я вижу вызов GET в Redis, но не вызов PUT.

Он никогда не будет кэшироваться, так как у вас есть unless = "#result != null", что означает, что не кешируйте, если результат не null. Таким образом, фактический результат вызова метода никогда не будет кэшироваться. В основном unless - это противоположность condition в аннотации @Cachable.

M. Deinum 17.07.2018 09:04
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
2
1
1 336
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваше кеширование и так должно работать нормально. Убедитесь, что у вас есть аннотация @EnableCaching и что ваши критерии unless верны.

Прямо сейчас вы используете unless = "#result != null", что означает, что он будет кэшировать результат, если только это не null. Это означает, что он почти никогда не будет кэшироваться, если только restTemplate.getForObject() не вернет null, или когда произойдет исключение, потому что тогда вы также вернете null.

Я предполагаю, что вы хотите кэшировать каждое значение, кроме null, но в этом случае вам нужно инвертировать свое условие, например:

@Cacheable(
    value = "com.example.webservice.api.AwesomeApi",
    key = "#query",
    unless = "#result == null") // Change '!=' into '=='

Или, как упоминалось в комментариях, вместо изменения условия, вы можете использовать condition вместо unless:

@Cacheable(
    value = "com.example.webservice.api.AwesomeApi",
    key = "#query",
    condition = "#result != null") // Change 'unless' into 'condition'

Вы также можете переименовать unless в condition и сохранить то, что у вас есть, чтобы сделать намерение немного более ясным.

Stephane Nicoll 17.07.2018 08:48

@StephaneNicoll Ты прав, не думал об этом. Я обновил свой ответ.

g00glen00b 17.07.2018 09:04

Что ж, обидно, что проблема оказалась такой маленькой ошибкой. К несчастью, это произошло потому, что кеш уже был введен, когда я добавил это условие. Итак, мне не удалось обнаружить эту проблему. В любом случае большое спасибо за вашу помощь.

nicholasnet 17.07.2018 15:21

Другие вопросы по теме