当前位置: 首页 > 知识库问答 >
问题:

Spring redis错误的结果

鲁华茂
2023-03-14

我使用Spring Redis和@Cacheable注释来实现两种方法。当我调用一个方法时,我会得到另一个方法的缓存结果。

当我使用@Cachebale注释为每个方法配置不同的缓存时,怎么可能从错误的缓存中得到结果?

安装:Spring版本4.1.6。Redis data 1.5和Redis client 2.7.0。

示例代码

@Cacheable("test1")
    public List<String> findSgsns() {
}

@Cacheable("test2")
    public List<String> findSgsns2() {
}

共有2个答案

宋涵衍
2023-03-14

默认情况下,如果未在@Cacheable注释中指定密钥,Spring将使用SimpleKeyGenerator生成密钥。

public class SimpleKeyGenerator implements KeyGenerator {

@Override
public Object generate(Object target, Method method, Object... params) 
{
    return generateKey(params);
}

/**
 * Generate a key based on the specified parameters.
 */
public static Object generateKey(Object... params) {
    if (params.length == 0) {
        return SimpleKey.EMPTY;
    }
    if (params.length == 1) {
        Object param = params[0];
        if (param != null && !param.getClass().isArray()) {
            return param;
        }
    }
    return new SimpleKey(params);
}
}

由于这两个方法(findSgsns()和findSgsns2())中都没有方法参数,因此它基本上会为这两个方法生成相同的缓存键。

您已经找到了一个解决方案,它基本上利用了redisTemplatebean中的usePrefix属性,在Redis中形成缓存键时,它基本上会增加您在@Cacheable注释中指定的值(即“test1”和“test2”)。为了完整起见,我想在这里再提两个备选方案:

>

  • 为每个方法指定自己的键(注意:可以使用Spring EL指定键):

    @Cacheable(value = "test1", key = "key1")
    public List<String> findSgsns() {
    }
    
    @Cacheable(value = "test2", key = "key2")
    public List<String> findSgsns2() {
    }
    

    构建一个自定义密钥生成器,下面是示例密钥生成器,它将方法名引入redis缓存密钥生成(注意:自定义密钥生成器将通过扩展CachingConfigrerSupport类自动生效):

    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
    
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    
    }
    

  • 公良鸿禧
    2023-03-14

    通过在spring配置中添加以下设置(set usePrefix)解决了该问题:

    <bean
        id="cacheManager"
        class="org.springframework.data.redis.cache.RedisCacheManager"
        c:template-ref="redisTemplate">
        <property name="usePrefix" value="true" />
    </bean>
    
     类似资料:
    • 导入java.util.Scanner;公共类GroupActivity{公共静态void main()

    • 我试图从我的数据库中得到一些数据,但我不会得到正确的结果。 我的方法: 所以应该有一个确切的结果,但我从控制台得到的全部是:日期的范围是从今天(6月12日-2周) CEST 2012年Tue Jun 12 14:49:11 2012年东部时间5月30日星期三14:49:11

    • 我正在使用JAXB/MOXY解组包含约50个此类对象的XML文件: BR

    • 结果似乎是程序只在AUART='yi01'的情况下获得所有销售订单(从表),而实际上我获得的是1.699.698个销售订单。因此,它忽略了select,,,中的其他参数,对于这些参数,我应该只得到77个结果。 非常感谢你的帮助

    • 您好,我正试图通过基于日期查询“where”来创建一个RESTAPI。我连接postgresql。 我有一个这样的实体 @Entity@Table(name="设备")公共类DeviceEntity{ 这是我的疑问: @存储库公共接口设备存储库扩展了分页和排序存储库{ 运行和测试url后,我得到错误"类型int的坏值:8962101012749336481"

    • 问题内容: 根据Wolfram Mathematica: cos(50) = 0.6427876096865394 ; 但是这段Java代码: 给出 0.9649660284921133 。 有什么问题吗? 问题答案: 期望参数以弧度为单位。这将返回您需要的结果: