我在@Service方法中保存一些值时遇到问题。我的代码:
@Service(value = "SettingsService") public class SettingsService { ... public String getGlobalSettingsValue(Settings setting) { getTotalEhCacheSize(); if(!setting.getGlobal()){ throw new IllegalStateException(setting.name() + " is not global setting"); } GlobalSettings globalSettings = globalSettingsRepository.findBySetting(setting); if(globalSettings != null) return globalSettings.getValue(); else return getGlobalEnumValue(setting) } @Cacheable(value = "noTimeCache", key = "#setting.name()") public String getGlobalEnumValue(Settings setting) { return Settings.valueOf(setting.name()).getDefaultValue(); }
我的存储库类:
@Repository public interface GlobalSettingsRepository extends CrudRepository<GlobalSettings, Settings> { @Cacheable(value = "noTimeCache", key = "#setting.name()", unless="#result == null") GlobalSettings findBySetting(Settings setting);
它应该像这样工作:
但它没有保存数据库或枚举中的任何数据。
我的缓存配置:
@Configuration @EnableCaching public class CacheConfig { @Bean public EhCacheCacheManager cacheManager(CacheManager cm) { return new EhCacheCacheManager(cm); } @Bean public EhCacheManagerFactoryBean ehcache() { EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); return ehCacheManagerFactoryBean; } }
我有一些示例来确保缓存在我的项目中以rest方法运行:
@RequestMapping(value = "/system/status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> systemStatus() { Object[] list = userPuzzleRepository.getAverageResponseByDateBetween(startDate, endDate); ... } public interface UserPuzzleRepository extends CrudRepository<UserPuzzle, Long> { @Cacheable(value = "averageTimeAnswer", key = "#startDate") @Query("select AVG(case when up.status='SUCCESS' OR up.status='FAILURE' OR up.status='TO_CHECK' then up.solvedTime else null end) from UserPuzzle up where up.solvedDate BETWEEN ?1 AND ?2") Object[] getAverageResponseByDateBetween(Timestamp startDate, Timestamp endDate);
而且运作良好。
我做错了什么?
您有两种方法SettingsService,一种是缓存的(getGlobalEnumValue(...)),另一种不是缓存的,但是调用了另一种方法(getGlobalSettingsValue(...))。
SettingsService
getGlobalEnumValue(...)
getGlobalSettingsValue(...)
但是,Spring缓存抽象的工作方式是通过代理类(使用Spring AOP)。但是,对同一类中的方法的调用将不会调用代理逻辑,而是在其下调用直接业务逻辑。这意味着如果您在同一个bean中调用方法,则缓存不起作用。
因此,如果您正在调用getGlobalSettingsValue(),它将不会填充,也不会在该方法调用时使用缓存getGlobalEnumValue(...)。
getGlobalSettingsValue()
可能的解决方案是:
@EnableCaching(mode = AdviceMode.ASPECTJ)