4

Redis を使用してエンティティのキ​​ャッシュ データを保存しようとしています。エンティティにはさまざまな種類のフィールドがあります。たとえば、

public class Job {
    private String id;
    private Date createTime; //Long
    private String submitterName;
    private JobDefinition jobDef;  //Another class
}

より多くのフィールドがあり、いくつかのフィールドは他のフィールドよりも頻繁に更新されるため、これjobを各フィールドをキーとして Redis の Hashmap として保存することにしました。ここでは、入れ子になったオブジェクト likejobDefは重要ではないので、for を使用Jackson2JsonRedisSerializerするhashValueSerializerRedisTemplatejobDefobj は長い JSON 文字列としてシリアル化されるだけで、私の場合はまったく問題ありません。

jobしかし、Redis からオブジェクト全体を効果的に逆シリアル化する方法がわかりません。私がデシリアライザーに設定したタイプは似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

2回目の編集:

JdkSerializationRedisSerializerHashValueSerializer として使用すると、逆シリアル化は正常に機能しRedisTemplateますが、これを使用する場合の欠点は、Redis に格納されている値が、 を使用した場合と同じ人間が読み取れる文字列値ではないことJackson2JsonRedisSerializerです。

4

1 に答える 1

13

には、実際のハッシュ構造への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生成されます。LinkedHashMapJobDefinition

インクルード タイプ情報を使用するとGenericJackson2JsonRedisSerializer、結果の Redis HASH は次のようになります。

127.0.0.1:6379> hgetall job:1
1) "id"
2) "\"1\""
...
7) "jobDef"
8) "{\"@class\":\"java.util.LinkedHashMap\",\"def\":\"nightwatch\"}"

これにより、値を正しく逆シリアル化できます。

もう 1 つのアプローチは特定の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 ハッシュを生成します。

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}"

残念ながらありませんJackson2HashMapperDATAREDIS-423に投票して、優先順位付けにご協力ください。

于 2016-02-18T07:45:36.720 に答える