我正在尝试使用Redis为我的实体存储一些缓存数据,其中包含不同类型的字段,例如,
public class Job {
private String id;
private Date createTime; //Long
private String submitterName;
private JobDefinition jobDef; //Another class
}
还有更多字段,并且由于几个字段的更新速度比其他字段更频繁,因此我决定将此job
保存为Redis中的Hashmap,并将每个字段作为键。这里像jobDef
这样的嵌套对象并不重要,所以我使用Jackson2JsonRedisSerializer
作为hashValueSerializer
RedisTemplate
,而jobDef
obj将被序列化为长JSON字符串,在我的情况下完全没问题。
但我不知道如何从Redis中有效地反序列化整个job
对象。我设置为反序列化器的类型与Jackson2JsonRedisSerializer(Map.class)
类似,但在反序列化字符串键和值时会产生抱怨。
这是RedisTemplate
的无效用法,或者我应该如何为它配置序列化工具?
编辑: 添加更多代码详细信息,
@Autowired
private StringRedisTemplate redisTemplate; //Here I'm using a String template as I need to use the same redisTemplate for some key-value/list operations too
Map jobHash= new ObjectMapper().convertValue(job, Map.class);
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer(Map.class));
redisTemplate.opsForHash().putAll("job:"+job.getId(), jobHash); //After this the job hash shows up in Redis as I expected, while the jobDef member is serialized and saved as a JSON string
Map jobMap = redisTemplate.opsForHash().entries("job:" + job.getId()); //But this won't work as it'll throw exception complaining cannot deserialize a String value to Map. But when I set Jackson2JsonRedisSerializer(String.class) it throws exception that cannot resolve the byte code
第二次编辑:
如果在JdkSerializationRedisSerializer
中使用RedisTemplate
作为HashValueSerializer,那么反序列化工作正常,但使用这个的缺点是存储在Redis中的值与使用{{时的人类可读字符串值不同1}}。
答案 0 :(得分:4)
Jackson2JsonRedisSerializer
不包括映射信息到实际的哈希结构中。
由此产生的Redis HASH导致类似:
127.0.0.1:6379> hgetall job:1
1) "id"
2) "\"1\""
3) "createTime"
4) "1455778716799"
5) "submitterName"
6) "\"Jon Snow\""
7) "jobDef"
8) "{\"def\":\"nightwatch\"}"
ObjectMapper
为LinkedHashMap
条目生成JobDefinition
,因为类型未知,无法反序列化。
使用GenericJackson2JsonRedisSerializer
包含类型信息,因此生成的Redis HASH如下所示:
127.0.0.1:6379> hgetall job:1
1) "id"
2) "\"1\""
...
7) "jobDef"
8) "{\"@class\":\"java.util.LinkedHashMap\",\"def\":\"nightwatch\"}"
这允许正确地反序列化值。
另一种方法是不使用特定的HashValueSerializer
,而是使用DecoratingStringHashMapper
和StringRedisTemplate
。
DecoratingStringHashMapper mapper = new DecoratingStringHashMapper<Job>(
new JacksonHashMapper<Job>(Job.class));
template.opsForHash().putAll("job:" + job.id, mapper.toHash(job));
Map jobMap = template.opsForHash().entries("job:" + job.id);
DecoratingStringHashMapper
将生成Redis Hash,如下所示:
127.0.0.1:6379> hgetall job:1
1) "id"
2) "1"
3) "createTime"
4) "1455780810643"
5) "submitterName"
6) "Jon Snow"
7) "jobDef"
8) "{def=nightwatch}"
不幸的是没有Jackson2HashMapper
。请投票给DATAREDIS-423并帮助我们确定优先顺序。