如何从 Spring 缓存中的 Spring 缓存中的缓存中按键获取单个项目 Spring Boot?
How to get individual item by key from cache in Spring cache in Spring Boot?
我们已经 spring-boot-starter-cache
添加到我们的项目中,并且没有使用缓存提供程序的任何特定实现。我们通过调用以下方法在应用程序启动期间加载所有数据:
@Override
@Cacheable(cacheNames = "foos")
public List<FooDto> getAllFoo() {
return fooRepository.findAll().stream()
.map(FooEntityDomainToDtoMapper::mapDomainToDto) // mapping entity to dto
.collect(Collectors.toList());
}
//Want to implement something like:
public FooDto getFoo(Long id) {
//return single object from foos(which are cached in above method)
}
它将所有 foos
存储在缓存中。正如预期的那样,下次我们调用 getAllFoo
时,它是从缓存中 returning 而不是从数据库中 returning。现在下次当用户通过 id 请求单个对象时,我们希望从这个已经缓存的 foos
数据中 return 它而不是调用 JPA 的 findById()
。有什么办法可以实现吗?
您是否有任何理由想要或需要将所有 Foos
缓存在您的应用程序中而不是单独缓存?
请记住,Spring 的缓存抽象 按照设计使用方法参数(如果有)作为键,return value 作为缓存条目的值。如果该方法没有参数,那么 Spring 将为您生成一个 ID。
我有 关于如何自定义 Spring 的 CacheManager
实现以缓存 Collection 个值 return 通过 @Cacheable
方法单独编辑。
但是,目前,我们假设您 need/want 缓存 Foos
的整个列表。
然后,要创建一个方法,通过 ID 从 Foos
的“缓存”列表中提取个人 Foo
,您可以在服务 class 中给定您的原始缓存方法],例如...
@Sevice
class MyFooService {
private final FooRepository<Foo, Long> fooRepository;
@Cacheable(cacheNames = "foos")
public List<FooDto> getAllFoos() {
return this.fooRepository.findAll().stream()
.map(FooEntityDomainToDtoMapper::mapDomainToDto) // mapping entity to dto
.collect(Collectors.toList());
}
}
然后,在另一个应用程序组件中,您可以...
@Component
class MyFooAccessor {
private final MyFooService fooService;
MyFooAccessor(MyFooService fooService) {
this.fooService = fooService;
}
Optional<FooDto> getById(Long id) {
this.fooService.getAllFoos().stream()
.filter(fooDto -> fooDto.getId().equals(id))
.findFirst();
}
...
}
MyFooAccessor
确保您不会规避缓存代理(即围绕MyFooService
由 Spring 应用)。如果 getById(..)
方法是 MyFooService
class 的成员,并直接调用 getAllFoos()
方法,您将绕过代理和缓存建议,导致每次访问数据库.
NOTE: You could use Spring AOP Load Time Weaving (LTW) (see doc) to avoid circumventing the caching proxy if you want to keep the getById(:Long)
method in the MyFooService
class with the getAllFoos()
, @Cacheable
method. However...
通常,您可以通过使用适当的设计模式(重新)适当地构造您的代码来解决这类问题。这也不是这里唯一的解决方案。 Spring 的美妙之处在于它给了你很多选择。这只是一种选择。
希望这有助于给你更多的想法。
使用密钥缓存对象,以便在从缓存中检索时可以使用该密钥。
@Override
@Cacheable(value = "fooByIDCache", key = "#id", unless = "#result == null")
public FooDto getFooByID(String id, FooDto fooDTO) {
return fooDTO;
}
我们已经 spring-boot-starter-cache
添加到我们的项目中,并且没有使用缓存提供程序的任何特定实现。我们通过调用以下方法在应用程序启动期间加载所有数据:
@Override
@Cacheable(cacheNames = "foos")
public List<FooDto> getAllFoo() {
return fooRepository.findAll().stream()
.map(FooEntityDomainToDtoMapper::mapDomainToDto) // mapping entity to dto
.collect(Collectors.toList());
}
//Want to implement something like:
public FooDto getFoo(Long id) {
//return single object from foos(which are cached in above method)
}
它将所有 foos
存储在缓存中。正如预期的那样,下次我们调用 getAllFoo
时,它是从缓存中 returning 而不是从数据库中 returning。现在下次当用户通过 id 请求单个对象时,我们希望从这个已经缓存的 foos
数据中 return 它而不是调用 JPA 的 findById()
。有什么办法可以实现吗?
您是否有任何理由想要或需要将所有 Foos
缓存在您的应用程序中而不是单独缓存?
请记住,Spring 的缓存抽象 按照设计使用方法参数(如果有)作为键,return value 作为缓存条目的值。如果该方法没有参数,那么 Spring 将为您生成一个 ID。
我有 CacheManager
实现以缓存 Collection 个值 return 通过 @Cacheable
方法单独编辑。
但是,目前,我们假设您 need/want 缓存 Foos
的整个列表。
然后,要创建一个方法,通过 ID 从 Foos
的“缓存”列表中提取个人 Foo
,您可以在服务 class 中给定您的原始缓存方法],例如...
@Sevice
class MyFooService {
private final FooRepository<Foo, Long> fooRepository;
@Cacheable(cacheNames = "foos")
public List<FooDto> getAllFoos() {
return this.fooRepository.findAll().stream()
.map(FooEntityDomainToDtoMapper::mapDomainToDto) // mapping entity to dto
.collect(Collectors.toList());
}
}
然后,在另一个应用程序组件中,您可以...
@Component
class MyFooAccessor {
private final MyFooService fooService;
MyFooAccessor(MyFooService fooService) {
this.fooService = fooService;
}
Optional<FooDto> getById(Long id) {
this.fooService.getAllFoos().stream()
.filter(fooDto -> fooDto.getId().equals(id))
.findFirst();
}
...
}
MyFooAccessor
确保您不会规避缓存代理(即围绕MyFooService
由 Spring 应用)。如果 getById(..)
方法是 MyFooService
class 的成员,并直接调用 getAllFoos()
方法,您将绕过代理和缓存建议,导致每次访问数据库.
NOTE: You could use Spring AOP Load Time Weaving (LTW) (see doc) to avoid circumventing the caching proxy if you want to keep the
getById(:Long)
method in theMyFooService
class with thegetAllFoos()
,@Cacheable
method. However...
通常,您可以通过使用适当的设计模式(重新)适当地构造您的代码来解决这类问题。这也不是这里唯一的解决方案。 Spring 的美妙之处在于它给了你很多选择。这只是一种选择。
希望这有助于给你更多的想法。
使用密钥缓存对象,以便在从缓存中检索时可以使用该密钥。
@Override
@Cacheable(value = "fooByIDCache", key = "#id", unless = "#result == null")
public FooDto getFooByID(String id, FooDto fooDTO) {
return fooDTO;
}