Десериализация в другой класс - данные Redis - PullRequest
1 голос
/ 06 января 2020

Работа на Spring Data Redis Я сериализую объект и сохраняю его в Redis. Стратегия сериализации - Jackson2JsonRedisSerializer. Итак, предположим, что мой bean-компонент Sample.java с некоторыми свойствами prop1, prop2 ниже показывает, как он добавляется в кеш

\xAC\xED\x00\x05sr\x00'com.main.model.Sample\x90\x91\xFB4\xDD\x9D\xE1\xBB\x02\x00\x11J\x00\x0Bprop1J\x00\x0Aprop2J

Как мы видим, информация о типе объекта Sample также сохраняется с его полностью квалифицированное имя.

Теперь есть несколько сервисов, которые работают с этой записью, десериализуя и обновляя ее, записывая обратно в кеш. (модели / bean-компоненты в различных сервисах имеют разные полностью квалифицированные имена)

Проблема возникает, когда другой сервис пытается десериализовать свою систему с ошибкой ClassNotFoundException

    org.springframework.data.redis.serializer.SerializationException:         
       Cannot serialize; nested exception is 
       org.springframework.core.serializer.support.SerializationFailedException: 
       Failed to deserialize object type; 
       nested exception is java.lang.ClassNotFoundException: com.xyz.model.BasicSample

Вот образец

Сервис 1

    @Override
    @Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
    public Sample fetchSample(Sample sample) {...}

Сервис 2

    @Override
    @Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
    public BasicSample fetchBasicSample(BasicSample sample) {...}

Есть ли способ либо

  • Прекратить хранить эту информацию

  • Игнорировать это при десериализации

  • Способ десериализации в объект другого класса с такими же свойствами

1 Ответ

1 голос
/ 02 февраля 2020

Я просто потратил полдня на ту же проблему, поэтому оставляю здесь ответ для будущих поколений:

Обычно Spring Data Redis будет использовать полное имя класса для ключа _class, но разработчик может настроить его с аннотацией @TypeAlias("someAlias"). Это переопределит поле _class.

Таким образом, вы можете определить два класса следующим образом:

package com.example.service1;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

@RedisHash(value = "sample")
@TypeAlias("SampleType")
public class Sample {
    @Indexed
    int id;

    String name;
    ...
}
package com.example.service2;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

@RedisHash(value = "sample")
@TypeAlias("SampleType")
public class Sample {
    @Indexed
    int id;

    String name;
    ...
}

Теперь объект redis будет десериализован независимо от имени пакета классов.

Ссылка на соответствующую документацию для получения дополнительной информации

...