反序列化为另一个类 – Spring数据Redis

huangapple go评论138阅读模式
英文:

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.

Link to the relevant documentation for more info

huangapple
  • 本文由 发表于 2020年1月6日 18:43:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610666.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定