无法反序列化负载。字节数组是DefaultDeserializer对应序列化的结果吗

问题描述 投票:0回答:2

我的Spring Boot项目使用

spring-boot-starter-data-redis
在redis上进行缓存,Oracle数据库进行持久化。它与当前版本 2.7.6 完美运行。我刚刚升级到3.0.5。源代码确实发生了很大变化,但 redis 的配置保持不变:

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return RedisCacheManager.builder(redisConnectionFactory)
                .transactionAware()
                .build();
    }

这是我的使用方法

@Cacheable

    @Autowired
    private ConfRepository confRepository;

    @Cacheable(value = "configCache", key = "{#root.methodName, #key}")
    @Override
    public Optional<Config> getByKey(String key) {
        return confRepository.findByKey(key);
    }

我用 2 个实例部署我的服务。问题是,当实例 1 中的

key
被放入
Cacheable
时,实例 2 无法反序列化,即在上面的方法中,我对实例 1 的第一个请求使用密钥
getByKey
key1
,我的第二个请求是实例 2 也带有
key1
应该命中缓存(从 redis 获取值并返回),但我得到了堆栈跟踪:

org.springframework.data.redis.serializer.SerializationException: Cannot deserialize
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:84)
    at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:46)
    at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.read(RedisSerializationContext.java:272)
    at org.springframework.data.redis.cache.RedisCache.deserializeCacheValue(RedisCache.java:277)
    at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:92)
    at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58)
    at org.springframework.cache.transaction.TransactionAwareCacheDecorator.get(TransactionAwareCacheDecorator.java:80)
    at org.springframework.cache.interceptor.AbstractCacheInvoker.doGet(AbstractCacheInvoker.java:73)
    at org.springframework.cache.interceptor.CacheAspectSupport.findInCaches(CacheAspectSupport.java:571)
    at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:536)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:402)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345)
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:702)
    at vn.com.tcbs.h2h.biz.service.impl.ConfigManagerServiceImpl$$SpringCGLIB$$0.getGroupRole(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:211)
    at jdk.proxy2/jdk.proxy2.$Proxy201.getGroupRole(Unknown Source)

Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:78)
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:36)
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:82)
    ... 219 common frames omitted
Caused by: java.lang.IllegalStateException: Could not identify any active SessionFactory having UUID 0105e7c4-c59a-46a6-a86e-23a65dde6ed6
    at org.hibernate.proxy.pojo.bytebuddy.SerializableProxy.retrieveMatchingSessionFactory(SerializableProxy.java:127)
    at org.hibernate.proxy.pojo.bytebuddy.SerializableProxy.readResolve(SerializableProxy.java:113)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1190)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2266)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1733)
    at java.base/java.io.ObjectInputStream$FieldValues.<init>(ObjectInputStream.java:2606)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2457)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2257)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1733)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:509)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:467)
    at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:71)
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:73)
    ... 221 common frames omitted

在这种情况下有人可以帮助我吗?

java spring-boot redis
2个回答
2
投票

问题是在 Hibernate 6 中,hibernate 对象缓存不起作用。因此,如果它是

FetchType.Lazy
并且您需要 Lazy 对象属性和
unproxy
缓存之前的对象,则需要加载完整的对象。

要取消代理对象,请使用

Hibernate.unproxy
方法。 更新代码:

@Cacheable(value = "configCache", key = "{#root.methodName, #key}")
@Override
public Optional<Config> getByKey(String key) {
    var config = confRepository.findByKey(key);
    var entity = config.isPresent() ? Hibernate.unproxy(config.get(), Config.class) : null;
    return Optional.ofNullable(entity);
}

在 Spring MVC 中升级到 Hibernate 6 后,我遇到了类似的问题。通过

unproxy
将 hibernate 对象保存到缓存中解决了这个问题。另外,通过 Spring Security 会话,我需要使用记录/POJO 类作为身份验证对象。

如果问题仍然存在,则使用记录/POJO 类存储在缓存中。因为不同实体的映射也会在序列化中添加hibernate类。

Hibernate 6:当多个服务器使用相同的缓存时,切勿将 hibernate 对象存储到缓存。

您可以使用RedisInsight浏览存储在redis中的数据并检查以获取更多详细信息。


0
投票

如果一个实例中的实体字段与另一实例中的实体字段不同,也可能会发生异常

因此,如果您的实例从不同的分支运行,请检查实体的字段。

© www.soinside.com 2019 - 2024. All rights reserved.