英文:
Deserialize into another class - Spring data redis
问题
在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
这里是一个示例
Service 1
@Override
@Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
public Sample fetchSample(Sample sample) {...}
Service 2
@Override
@Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
public BasicSample fetchBasicSample(BasicSample sample) {...}
有没有办法要么
-
停止存储这个信息
-
在反序列化时忽略它
-
以相同属性的不同类对象反序列化的方法
英文:
Working on Spring Data Redis I serialize an object and store it into Redis. The serialization strategy is Jackson2JsonRedisSerializer
. So, suppose my bean is Sample.java
with some properties prop1, prop2
below is how it is added into the cache
\xAC\xED\x00\x05sr\x00'com.main.model.Sample\x90\x91\xFB4\xDD\x9D\xE1\xBB\x02\x00\x11J\x00\x0Bprop1J\x00\x0Aprop2J
As we can see the object type info Sample
is also stored with its fully qualified name.
Now there are multiple services which work on this entry by deserializing and updating it writing back into cache. (The models/beans in various services have different fully qualified names)
The problem occurs when a different service tries to deserialize it failing with 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
Here is a sample
Service 1
@Override
@Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
public Sample fetchSample(Sample sample) {...}
Service 2
@Override
@Cacheable(value = "sample", key = "{ #sample.sampleId }", unless = "#result == null")
public BasicSample fetchBasicSample(BasicSample sample) {...}
Is there a way to either
-
Stop storing this info
-
Ignore this while deserialization
-
A way to deserialize into a different class object with same properties
答案1
得分: 2
通常,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 对象将独立于类的包名称进行反序列化。
英文:
I just spent half a day on the same issue so leaving the answer here for the future generations:
Generally, the Spring Data Redis will use the full class name for the _class key, but the dev can customize it with a @TypeAlias("someAlias")
annotation. This will override the _class field.
Thus you can define the two classes as:
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;
...
}
Now the redis object will be deserialized independently of the classes package name.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论