在使用redisTemplate.opsForSet().members(key)获取key String; value Set<Entity>数据时候出现如下问题。
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property ‘@Class’ at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 322]
Could not resolve type id ‘xxx.xxx.Entity’ as a subtype of [simple type, class java.lang.Object]: no such class found
github的issue中出现和我一样的问题 https://github.com/redisson/redisson/issues/1865
在redis存放数据实体Entity数据时候,redis也把当前的Entity类全路径存放进去了。如果redis的value中的Entity类全路径 和取出映射的全限定名不一致就会报错。
redis存放的Entity类中的字段与取出数据时候映射的Entity类字段不一致也会报错。
解决方式,存进去的Entity路径和取出映射的全限定名要保持一致
定义好Lua脚本
local poem_id = redis.call('get', KEYS[1]) return redis.call('get', 'poem_id_'..poem_id)脚本意思: 指定一个key,通过这个key获取到内容poem_id,在根据获取到的内容poem_id作为第二行key,再次查询并返回结果。
Lua脚本写好了,把它组成redis-cli能够识别的命令。 eval是告诉redis-cli你需要执行脚本,字符串中是脚本内容,后面的数字1表示有几个key,最后是真正传入的key内容。 eval "local poem_id = redis.call('get', KEYS[1]) return redis.call('get', 'poem_id_'..poem_id)" 1 poem_verse_争似秦楼萧史伴
直接上代码,注意的是 java代码key1 就是填充Lua脚本的 KEYS[1] 内容
String lua = "return redis.call('get', KEYS[1])"; System.out.println(lua); DefaultRedisScript<String> rs = new DefaultRedisScript<String>(); //设置脚本 rs.setScriptText(lua); //定义返回类型。注意如果没有这个定义,spring不会返回结果 rs.setResultType(String.class); RedisSerializer<String> stringRedisSerializer = redisTemplate.getStringSerializer(); //这里的key1就是Lua脚本的 KEYS[1] 内容 String key1 = "poem_verse_日长睡起"; //定义key List<String> keyList = new ArrayList<String>(); keyList.add(key1); String luaScriptResult = (String) redisTemplate.execute(rs, stringRedisSerializer, stringRedisSerializer, keyList);RedisSerializer<String> stringRedisSerializer = redisTemplate.getStringSerializer() 是redis返回结果,然后对结果进行序列化处理。这里处理成string。 可能你存放的value不是string而是一个Entity。就是这样的
Entity luaScriptResult = (Entity) redisTemplate.execute(rs, keyList);luaScriptResult是执行出的结果
水平原因可能存在错误,希望指正 chenrui@marsdl.com