Spring 缓存 ehcache 问题
Spring caching ehcache issue
我无法为 ehcache 正确设置缓存,Spring boot 1.5.2
@EnableCaching
@EnableScheduling
@SpringBootApplication
public class CacheTestConfig extends SpringBootServletInitializer {
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
factory.setConfigLocation(new ClassPathResource("ehcache.xml"));
factory.setShared(true);
return factory;
}
}
ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="pujcka"
maxEntriesLocalHeap="100"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
PujckaCachingRepository .java
public interface PujckaCachingRepository extends CrudRepository<Pujcka, Integer> {
static final String CACHE_MAME = "pujcka";
@Override
@Cacheable(cacheNames = CACHE_MAME, key = "#id", condition = "#id != null") // each calling select into DB - not cached
//@Cacheable(cacheNames = CACHE_MAME, key = "#id", condition = "#id == null") //IllegalArgumentException Popis: Null key returned for cache operation
//@Cacheable(cacheNames = CACHE_MAME)
Pujcka findOne(Integer id);
@Override
@Cacheable(cacheNames = CACHE_MAME)
Iterable<Pujcka> findAll();
@Override
//@CachePut(cacheNames = CACHE_MAME, key = "#pujcka.id") //URL: http://localhost:8081/pujcka/nova Vyjimka: SpelEvaluationException Popis: EL1007E: Property or field 'id' cannot be found on null
@CachePut(cacheNames = CACHE_MAME)
<S extends Pujcka> S save(S pujcka);
@CacheEvict(cacheNames = CACHE_MAME)
default void refreshAll() {
//This method will remove all 'products' from cache, say as a result of flush API.
}
}
Pujcka.java
@Entity
@ToString
@Getter @Setter
public class Pujcka implements Serializable{
private static final long serialVersionUID = -1385887062145410511L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
PujckaController.java
@Controller
@RequestMapping("pujcka")
public class PujckaController extends RootController {
@Autowired
private PujckaCachingRepository pujckaCachingRepository;
@RequestMapping(value = "nova", method = RequestMethod.POST)
public String ulozPujcku(@Valid Pujcka pujcka, BindingResult bindingResult, Model model) {
pujckaCachingRepository.save(pujcka);
pujckaCachingRepository.refreshAll();
return "redirect:/pujcka/seznam";
}
@RequestMapping(value = "seznam", method = RequestMethod.GET)
public String seznam(Model model) {
model.addAttribute("pujckaList", pujckaCachingRepository.findAll());
return getRequestPath();
}
@RequestMapping(value = "edit/id/{id}", method = RequestMethod.GET)
public String edit(@PathVariable Integer id, Model model) {
Pujcka pujcka = pujckaCachingRepository.findOne(id);
model.addAttribute("pujcka", pujcka);
return "pujcka/nova";
}
当我刷新 http://localhost:8081/pujcka/seznam 时,第一次调用是从数据库中获取数据,第二次调用是使用缓存中的数据。这工作正常。
当我刷新http://localhost:8081/pujcka/edit/id/1时,每次都调用数据库并且缓存不工作。 ---为什么???--- 我做错了什么?
当我编辑并保存数据时,select 全部触发并更新列表,下一次刷新从缓存中填充 - 工作正常
此设置使用缓存,但缓存中是旧值
//@Cacheable(cacheNames = CACHE_MAME)
Pujcka findOne(Integer id);
感谢帮助
更新 1 - 这有帮助,谢谢 jmw5598
@Cacheable(cacheNames = CACHE_MAME, key = "#p0")
Pujcka findOne(Integer id);
@CachePut(cacheNames = CACHE_MAME, key="#result.id")
<S extends Pujcka> S save(S pujcka);
@CacheEvict(cacheNames = CACHE_MAME)
default void refreshAll() {
}
@Cacheable(cacheNames = CACHE_MAME)
Iterable<Pujcka> findAll();
在控制器中
pujckaCachingRepository.save(pujcka);
pujckaCachingRepository.refreshAll();
我删除了 refreshAll() 方法并尝试编辑一些行。调用 findOne(id) 是缓存工作,但 findAll() 没有更新,所以我 return refreshAll() 方法回来了。
这是否正确,或者有什么方法可以在编辑项目并调用 save(pujcka) 后更新 findAll() 中的缓存?
由于您使用的是 Spring Data JPA,我认为您不能直接通过名称引用参数。不过,您可以使用 SpEL 元数据来引用参数。
@Override
@Cacheable(cacheNames = CACHE_MAME, key = "#p0", condition = "#p0 != null")
Pujcka findOne(Integer id);
同样对于 @CachePut
,您可以使用结果元数据项来引用结果对象 ID(或您想要用作键的任何字段)。
@Override
@CachePut(cacheNames = CACHE_MAME, key="#result.id")
<S extends Pujcka> S save(S pujcka);
我无法为 ehcache 正确设置缓存,Spring boot 1.5.2
@EnableCaching
@EnableScheduling
@SpringBootApplication
public class CacheTestConfig extends SpringBootServletInitializer {
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
factory.setConfigLocation(new ClassPathResource("ehcache.xml"));
factory.setShared(true);
return factory;
}
}
ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="pujcka"
maxEntriesLocalHeap="100"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
PujckaCachingRepository .java
public interface PujckaCachingRepository extends CrudRepository<Pujcka, Integer> {
static final String CACHE_MAME = "pujcka";
@Override
@Cacheable(cacheNames = CACHE_MAME, key = "#id", condition = "#id != null") // each calling select into DB - not cached
//@Cacheable(cacheNames = CACHE_MAME, key = "#id", condition = "#id == null") //IllegalArgumentException Popis: Null key returned for cache operation
//@Cacheable(cacheNames = CACHE_MAME)
Pujcka findOne(Integer id);
@Override
@Cacheable(cacheNames = CACHE_MAME)
Iterable<Pujcka> findAll();
@Override
//@CachePut(cacheNames = CACHE_MAME, key = "#pujcka.id") //URL: http://localhost:8081/pujcka/nova Vyjimka: SpelEvaluationException Popis: EL1007E: Property or field 'id' cannot be found on null
@CachePut(cacheNames = CACHE_MAME)
<S extends Pujcka> S save(S pujcka);
@CacheEvict(cacheNames = CACHE_MAME)
default void refreshAll() {
//This method will remove all 'products' from cache, say as a result of flush API.
}
}
Pujcka.java
@Entity
@ToString
@Getter @Setter
public class Pujcka implements Serializable{
private static final long serialVersionUID = -1385887062145410511L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
PujckaController.java
@Controller
@RequestMapping("pujcka")
public class PujckaController extends RootController {
@Autowired
private PujckaCachingRepository pujckaCachingRepository;
@RequestMapping(value = "nova", method = RequestMethod.POST)
public String ulozPujcku(@Valid Pujcka pujcka, BindingResult bindingResult, Model model) {
pujckaCachingRepository.save(pujcka);
pujckaCachingRepository.refreshAll();
return "redirect:/pujcka/seznam";
}
@RequestMapping(value = "seznam", method = RequestMethod.GET)
public String seznam(Model model) {
model.addAttribute("pujckaList", pujckaCachingRepository.findAll());
return getRequestPath();
}
@RequestMapping(value = "edit/id/{id}", method = RequestMethod.GET)
public String edit(@PathVariable Integer id, Model model) {
Pujcka pujcka = pujckaCachingRepository.findOne(id);
model.addAttribute("pujcka", pujcka);
return "pujcka/nova";
}
当我刷新 http://localhost:8081/pujcka/seznam 时,第一次调用是从数据库中获取数据,第二次调用是使用缓存中的数据。这工作正常。
当我刷新http://localhost:8081/pujcka/edit/id/1时,每次都调用数据库并且缓存不工作。 ---为什么???--- 我做错了什么?
当我编辑并保存数据时,select 全部触发并更新列表,下一次刷新从缓存中填充 - 工作正常
此设置使用缓存,但缓存中是旧值
//@Cacheable(cacheNames = CACHE_MAME)
Pujcka findOne(Integer id);
感谢帮助
更新 1 - 这有帮助,谢谢 jmw5598
@Cacheable(cacheNames = CACHE_MAME, key = "#p0")
Pujcka findOne(Integer id);
@CachePut(cacheNames = CACHE_MAME, key="#result.id")
<S extends Pujcka> S save(S pujcka);
@CacheEvict(cacheNames = CACHE_MAME)
default void refreshAll() {
}
@Cacheable(cacheNames = CACHE_MAME)
Iterable<Pujcka> findAll();
在控制器中
pujckaCachingRepository.save(pujcka);
pujckaCachingRepository.refreshAll();
我删除了 refreshAll() 方法并尝试编辑一些行。调用 findOne(id) 是缓存工作,但 findAll() 没有更新,所以我 return refreshAll() 方法回来了。
这是否正确,或者有什么方法可以在编辑项目并调用 save(pujcka) 后更新 findAll() 中的缓存?
由于您使用的是 Spring Data JPA,我认为您不能直接通过名称引用参数。不过,您可以使用 SpEL 元数据来引用参数。
@Override
@Cacheable(cacheNames = CACHE_MAME, key = "#p0", condition = "#p0 != null")
Pujcka findOne(Integer id);
同样对于 @CachePut
,您可以使用结果元数据项来引用结果对象 ID(或您想要用作键的任何字段)。
@Override
@CachePut(cacheNames = CACHE_MAME, key="#result.id")
<S extends Pujcka> S save(S pujcka);