弹簧分别缓存列表中的所有元素

我正在尝试将缓存添加到CRUD应用程序,我开始做这样的事情:

@Cacheable("users")
List<User> list() {
    return userRepository.findAll()
}
@CachePut(value = "users", key = "#user.id") 
void create(User user) {
    userRepository.create(user)
}
@CachePut(value = "users", key = "#user.id") 
void update(User user) {
    userRepository.update(user)
}
@CacheEvict(value = "users", key = "#user.id") 
void delete(User user) {
    userRepository.delete(user)
}

我遇到的问题是,我希望创建/更新/删除操作可以更新已存储在缓存中的操作元素(请注意,这不是从数据库拉取而是从数据引擎中提取),但我无法做到这一点。list()list()

我想单独缓存 返回的所有元素,以便所有其他操作都可以使用 更新缓存。或者,进行所有操作以更新已存储在缓存中的列表。list()#user.id

我读到我可以在更新时逐出整个缓存,但我想避免这样的事情:

@CacheEvict(value = "users", allEntries=true) 
void create(User user) {
    userRepository.create(user)
}

有没有办法在缓存的集合中创建/更新/删除值?还是将集合中的所有值缓存为单个键?


答案 1

我会自我回答我的问题,因为没有人给任何东西,可以帮助别人。

我在处理此问题时遇到的问题是对缓存使用情况的误解问题。我在这个问题上发布的需求与如何更新缓存列表的成员(方法响应)有关。这个问题不能用缓存解决,因为缓存的值是列表本身,我们无法部分更新缓存的值。

我想解决这个问题的方式与“地图”或分布式地图有关,但我想使用注释。通过使用分布式地图,可以在不使用 .因此,返回的列表可能已更新。@Cacheable@Cacheable

所以,我(想要)从其他角度解决这个问题。每当缓存需要更新时,我都会使用此代码刷新它。@Cacheable

我用下面的代码来解决我的问题:

@Cacheable("users")
List<User> list() {
    return userRepository.findAll()
}
// Refresh cache any time the cache is modified
@CacheEvict(value = "users", allEntries = true") 
void create(User user) {
    userRepository.create(user)
}
@CacheEvict(value = "users", allEntries = true") 
void update(User user) {
    userRepository.update(user)
}
@CacheEvict(value = "users", allEntries = true") 
void delete(User user) {
    userRepository.delete(user)
}

此外,我还启用了spring缓存的日志记录输出,以确保/了解缓存的工作原理:

# Log Spring Cache output
logging.level.org.springframework.cache=TRACE

答案 2

不确定,使用Spring的@Cacheable对你来说是一个艰难的限制,但这基本上对我有用。

我尝试使用Spring的RedisTemplate和Redis HasMap数据结构来存储列表元素。

存储单个用户:

redisTemplate.opsForHash().put("usersRedisKey" ,user.id,user);

存储用户列表:

需要先用 user.id 映射

Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

    redisTemplate.opsForHash().putAll("usersRedisKey", userMap);

从缓存中获取单个用户:

redisTemplate.opsForHash().get("usersRedisKey",user.id);

获取用户列表:

redisTemplate.opsForHash().multiGet("usersRedisKey", userIds); //userIds is List of ids

从列表中删除用户:

redisTemplate.opsForHash().delete("usersRedisKey",user.id);

同样,您可以尝试使用 Redis HashMap 中的其他操作来更新基于 id 的单个对象。

我知道我来晚了,但请告诉我这是否适合您。