【问题标题】:Spring cache, same key on different cachesSpring缓存,不同缓存上的相同键
【发布时间】:2017-03-28 07:25:50
【问题描述】:

我正在尝试使用两个缓存来存储具有相同 ID 的两个不同项目,用户和组。我希望我应该得到不同的值,因为它们是两个不同的缓存。但事实并非如此。

@Bean
public JedisConnectionFactory jedisConnectionFactory() {
    LOG.debug("redis host: {}, redis port: {}", redisHost, redisPort);
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setUseSsl(true);
    factory.setHostName(redisHost);
    factory.setPort(redisPort);
    factory.setUsePool(true);
    factory.setPassword(primaryKey);
    return factory;
}

/**
 *
 * @return
 */
@Bean(name = "redisTemplate")
public RedisTemplate redisTemplate() {
    RedisTemplate template = new RedisTemplate();
    template.setConnectionFactory(jedisConnectionFactory());
    return template;
}

/**
 *
 * @return
 */
@Bean
public CacheManager cacheManager() {
    RedisCacheManager manager = new RedisCacheManager(redisTemplate());
    manager.setCacheNames(Arrays.asList("users", "groups"));
    return manager;
}

@Cacheable(cacheNames = "users", key = "#id")
public User findUserById(String id) {
    return null;
}

@Cacheable(cacheNames = "users", key = "#user.id")
public User updateUser(User user) {
    return user;
}

@Cacheable(cacheNames = "groups", key = "#id")
public Group findGroupById(String id) {
    return null;
}

@CachePut(cacheNames = "groups", key = "#group.id")
public Group updateGroup(Group group) {
    return group;
}

JUnit。

    service.removeCaches();

    User user = new User();
    user.setName("oldUser");
    user.setId("1");


    // USER
    assertNull(service.findUserById("1"));

    service.updateUser(user);

    User userCached = service.findUserById("1");
    LOG.debug(userCached);
    assertNotNull(userCached);
    assertEquals(userCached.getName(), "oldUser");

    // GROUP
    assertNull(service.findGroupById("1")); // <== here, im actually getting user instead of null. cache has been cleared before the test starts. 

也许我在这里误解了不同缓存的概念。或者,即使在不同的缓存中,键也应该是唯一的?

日志

 Results :

Tests in error: 
  testCache(TestRedisServiceImpl): User cannot be cast to Group

这基本上表示从缓存中返回了一个用户。

【问题讨论】:

  • 你为什么说你得到的是一个用户而不是一个组?有没有日志显示?
  • 您的代码不完整...您可以发布您的 JUnit 的完整代码吗?
  • 我添加了日志。 @reos
  • 我添加了缓存定义部分。 @javaguy
  • 我突然想起我以前看过这个。 stackoverflow.com/questions/18145372/…

标签: java spring caching


【解决方案1】:

其实CacheManager.setCacheNames()为同一个缓存提供别名,并不是两个不同的缓存。 可以看APIhere

void setCacheNames(Collection cacheNames) 指定集合 此 CacheManager 的“静态”模式的缓存名称。

您可以认为 CacheManager 就像一个 Map 对象,其中一个键将仅存储一个对象(作为值),因此当您尝试使用相同键插入第二个对象时,第一个对象将是替换为第二个对象。

所以,正在发生的事情是 CacheManager 中的 user 对象被 group 对象替换,因为它们都使用相同的键存储。

要使缓存键在缓存管理器中唯一,您可以使用cacheManager.setUsePrefix(),这样每个键都将以各自的缓存名称作为前缀,并且值不会被替换。

【讨论】:

  • 感谢您的澄清。我不明白使用多个缓存管理器的一件事是数据如何存储在缓存中。相同的 ID 如何在缓存系统中持久存在。如果我重新启动 Web 应用程序,它如何知道应该将哪些数据加载到哪个缓存中。将 usePrefix 设置为 true 也符合我的需求。 stackoverflow.com/questions/18145372/…
  • 你是对的,你可以使用 usePrefix 这样key就不同了,因为它们带有cachename前缀
  • 是的。它正在使用前缀。我犹豫是否使用多个缓存管理器,因为不知道数据如何存储在缓存系统中,以及当应用程序重新启动时它们是否会被注入回正确的缓存管理器。
猜你喜欢
  • 2015-05-07
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多