千家信息网

如何解决@CachePut设置的key值无法与@CacheValue的值匹配问题

发表于:2024-10-01 作者:千家信息网编辑
千家信息网最后更新 2024年10月01日,这篇文章主要介绍如何解决@CachePut设置的key值无法与@CacheValue的值匹配问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!@CachePut设置的key值无
千家信息网最后更新 2024年10月01日如何解决@CachePut设置的key值无法与@CacheValue的值匹配问题

这篇文章主要介绍如何解决@CachePut设置的key值无法与@CacheValue的值匹配问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

@CachePut设置的key值无法与@CacheValue的值匹配

缓存注解key的基本数据类型要求必须要统一

//根据id查询缓存的值@Cacheable(value = "testCache")public TestEntity listById(int id){    return  testMapper.listById(id);}//修改缓存的值@CachePut(value = "testCache" ,key = "#result.id")public TestEntity updateById(TestEntity testEntity){    System.out.println("运行结果:"+testMapper.updateById(testEntity));    System.out.println("id:"+testEntity.getId());    return testEntity;}
//实体类修改前public class TestEntity {    private String id;//注意这里    private String name;    private String sex;}
//实体类修改后public class TestEntity {    private int id;    private String name;    private String sex;}

现在修改完成可以总结出来一个结论,key的基本数据类型要求必须要统一。

在cache中,数据类型的要求是非常严格的,同样的id的为1,int类型和String类型是不同。

我一开始在这个错误上面困扰了好久,因为mybatis返回的结果中,对于int和String类型的id并没有提示什么错误,一开始打断点,扒源码发现对这个key的生成并没有什么改变,我写的result.id一直传到了生成id的地方,尽管如何生成的并没有看的十分明白。

直到今天我再反复测试的时候,在写到"result."的时候忽然发现id是String类型的才恍然大悟。

Spring-Cache key设置注意事项

为了提升项目的并发性能,考虑引入本地内存Cache,对:外部数据源访问、Restful API调用、可重用的复杂计算 等3种类型的函数处理结果进行缓存。目前采用的是Spring Cache的@Cacheable注解方式,缓存具体实现选取的是Guava Cache。

具体缓存的配置此处不再介绍,重点对于key的配置进行说明:

1、基本形式

@Cacheable(value="cacheName", key"#id")public ResultDTO method(int id);

2、组合形式

@Cacheable(value="cacheName", key"T(String).valueOf(#name).concat('-').concat(#password))public ResultDTO method(int name, String password);

3、对象形式

@Cacheable(value="cacheName", key"#user.id)public ResultDTO method(User user);

4、自定义Key生成器

@Cacheable(value="gomeo2oCache", keyGenerator = "keyGenerator")public ResultDTO method(User user);

有一个尤其需要注意的坑:Spring默认的SimpleKeyGenerator是不会将函数名组合进key中的

举个栗子

@Component    public class CacheTestImpl implements CacheTest {        @Cacheable("databaseCache")        public Long test1()        { return 1L; }         @Cacheable("databaseCache")        public Long test2()        { return 2L; }         @Cacheable("databaseCache")        public Long test3()        { return 3L; }         @Cacheable("databaseCache")        public String test4()        { return "4"; }     }

我们期望的输出是:

1
2
3
4

而实际上的输出是:

1
1
1
ClassCastException: java.lang.Long cannot be cast to java.lang.String

此外,原子类型的数组,直接作为key使用也是不会生效的

为了解决上述2个问题,自定义了一个KeyGenerator如下:

class CacheKeyGenerator implements KeyGenerator {     // custom cache key    public static final int NO_PARAM_KEY = 0;    public static final int NULL_PARAM_KEY = 53;        @Override    public Object generate(Object target, Method method, Object... params) {         StringBuilder key = new StringBuilder();        key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");        if (params.length == 0) {            return key.append(NO_PARAM_KEY).toString();        }        for (Object param : params) {            if (param == null) {                log.warn("input null param for Spring cache, use default key={}", NULL_PARAM_KEY);                key.append(NULL_PARAM_KEY);            } else if (ClassUtils.isPrimitiveArray(param.getClass())) {                int length = Array.getLength(param);                for (int i = 0; i < length; i++) {                    key.append(Array.get(param, i));                    key.append(',');                }            } else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {                key.append(param);            } else {                log.warn("Using an object as a cache key may lead to unexpected results. " +                        "Either use @Cacheable(key=..) or implement CacheKey. Method is " + target.getClass() + "#" + method.getName());                key.append(param.hashCode());            }            key.append('-');        }         String finalKey = key.toString();        long cacheKeyHash = Hashing.murmur3_128().hashString(finalKey, Charset.defaultCharset()).asLong();        log.debug("using cache key={} hashCode={}", finalKey, cacheKeyHash);        return key.toString();    }}

采用此方式后可以解决:多参数、原子类型数组、方法名识别 等问题

以上是"如何解决@CachePut设置的key值无法与@CacheValue的值匹配问题"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

类型 缓存 问题 数据 生成 形式 结果 内容 函数 原子 实体 数组 方式 时候 注解 篇文章 错误 组合 统一 输出 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 软件开发外包一个人多少钱 广东广电家庭服务器指示灯不亮 不同的系统可以使用一个服务器吗 如何给服务器安装系统 上海安装网络技术要多少钱 新罗区捷步品裕网络技术服务部 普刊数据库 转录后调控预测数据库 象过河软件数据库无法加载 山东保险软件开发公司电话 计算机网络服务器跟港口 服务器系统一般是什么系统 土地调查数据库是什么意思 服务器可以叫2b2t吗 不死鸟固件支持打印服务器不 澪pro宝可梦模组的服务器 山西网络卫星授时服务器 百事网络技术有限公司 四川渝惠捷保网络技术有限公司 顺其自然数据库配图 系统集成软件开发部门职责 如何给服务器安装系统 比奇网络技术前台电话 计算机软件开发方向 服务器内部结构介绍 国家怎么建立dna数据库 戴尔计算机网络技术 sql如何导出数据库 杨丰岭网络安全宣传 无法将项目保存到数据库
0