Spring boot sprng启动jpa+;redis LazyInitializationException
我使用SpringBoot2.1.2和redis作为缓存提供程序 但是现在,我有一个问题Spring boot sprng启动jpa+;redis LazyInitializationException,spring-boot,spring-data-jpa,spring-data-redis,Spring Boot,Spring Data Jpa,Spring Data Redis,我使用SpringBoot2.1.2和redis作为缓存提供程序 但是现在,我有一个问题 在sysUser实体中 redis配置 其他 我尝试这些方法 @JsonIgnore,但它将设置角色为空,我想使用此字段 配置jackson registerModuleHibernate5模块,它将设置角色为null 使用代理(lazy=false),不做任何更改 使用@ManyToMany(fetch=FetchType.EAGER),不做任何更改 配置 没有变化 使用其他json工具,如gson和F
@JsonIgnore
,但它将设置角色
为空
,我想使用此字段Hibernate5模块
,它将设置角色
为null
@ManyToMany(fetch=FetchType.EAGER)
,不做任何更改如果没有解决方法,也许我必须使用Mybatis。但是还有很多工作要做。请帮我解决这个问题…在您的代码中,您会像这样返回valueSerializer
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
private重新序列化程序valueSerializer(){
返回新的GenericJackson2JsonRedisSerializer();
}
但是您必须返回GenericJackson2JsonRedisSerializer,其中包含注册为模块的HibernateModule或Hibernate4Module的Jackson对象映射器
public ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
mapper.enable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// Registering Hibernate5Module to support lazy objects for hibernate 5
// Use Hibernate4Module if using hibernate 4
mapper.registerModule(new Hibernate5Module());
return mapper;
}
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer(getMapper());
}
public ObjectMapper getMapper(){
ObjectMapper mapper=新的ObjectMapper();
enable(MapperFeature.ACCEPT\u不区分大小写\u枚举);
enable(SerializationFeature.FAIL\u ON\u EMPTY\u bean);
configure(SerializationFeature.FAIL\u ON\u EMPTY\u bean,false);
//注册Hibernate5模块以支持hibernate 5的惰性对象
//如果使用hibernate 4,请使用Hibernate4模块
registerModule(新的Hibernate5Module());
返回映射器;
}
私有重新序列化程序valueSerializer(){
返回新的GenericJackson2JsonRedisSerializer(getMapper());
}
1st。在下面创建2个类
HibernateCollectionIdResolver.class将HibernateCollection类转换为JDK集合类,因此Jackson将从
{
"paramA": [
"org.hibernate.collection.internal.PersistentSet",
[]
]
}
到
然后,typeFromId方法将从上面的类全名中获取JDK JavaType,以将json反序列化为POJO
class HibernateCollectionIdResolver extends TypeIdResolverBase {
public HibernateCollectionIdResolver() {
}
@Override
public String idFromValue(Object value) {
//translate from HibernanteCollection class to JDK collection class
if (value instanceof PersistentArrayHolder) {
return Array.class.getName();
} else if (value instanceof PersistentBag || value instanceof PersistentIdentifierBag || value instanceof PersistentList) {
return List.class.getName();
} else if (value instanceof PersistentSortedMap) {
return TreeMap.class.getName();
} else if (value instanceof PersistentSortedSet) {
return TreeSet.class.getName();
} else if (value instanceof PersistentMap) {
return HashMap.class.getName();
} else if (value instanceof PersistentSet) {
return HashSet.class.getName();
} else {
//default is JDK collection
return value.getClass().getName();
}
}
@Override
public String idFromValueAndType(Object value, Class<?> suggestedType) {
return idFromValue(value);
}
//deserialize the json annotated JDK collection class name to JavaType
@Override
public JavaType typeFromId(DatabindContext ctx, String id) throws IOException {
try {
return ctx.getConfig().constructType(Class.forName(id));
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException(e);
}
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CLASS;
}
}
第二。向ObjectMapper注册此MixIn类
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new JodaModule());
mapper.addMixIn(Collection.class, HibernateCollectionMixIn.class);
jackson2JsonRedisSerializer.setObjectMapper(mapper);
Jackson2JsonRedisSerializer Jackson2JsonRedisSerializer=新的Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper=新的ObjectMapper();
enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);
registerModule(新的Jdk8Module());
registerModule(新的JavaTimeModule());
registerModule(新的JodaModule());
addMixIn(Collection.class,HibernateCollectionMixIn.class);
setObjectMapper(映射器);
最后,将jackson2JsonRedisSerializer注册到RedisCacheConfiguration
这将是有帮助的,我花了2天研究如何解决这个问题。
我发现json类型id可以重写。。。
所以只需覆盖jackson typeIdResolver~
编辑:解决反序列化问题并添加一些评论您好,我也有同样的问题,但这段代码可能会解决这个问题,如何以及为什么解决这个问题会真正有助于提高您的帖子质量,并可能导致更多的投票。请记住,你是在将来回答读者的问题,而不仅仅是现在提问的人。请您的回答添加解释,并说明适用的限制和假设。@БББГааааПаа好的,还有一些反序列化问题需要解决…@beijiaxu这对我来说太完美了,不能再感谢您了
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: cn.echocow.xiaoming.model.entity.SysUser["roles"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: cn.echocow.xiaoming.model.entity.SysUser["roles"])
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:132)
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:110)
at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:48)
......
Caused by: com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: cn.echocow.xiaoming.model.entity.SysUser["roles"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
......
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:160)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:287)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:302)
......
spring:
jpa:
open-in-view: true
properties
hibernate:
enable_lazy_load_no_trans: true
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
public ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
mapper.enable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// Registering Hibernate5Module to support lazy objects for hibernate 5
// Use Hibernate4Module if using hibernate 4
mapper.registerModule(new Hibernate5Module());
return mapper;
}
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer(getMapper());
}
{
"paramA": [
"org.hibernate.collection.internal.PersistentSet",
[]
]
}
{
"paramA": [
"java.util.HashSet",
[]
]
}
class HibernateCollectionIdResolver extends TypeIdResolverBase {
public HibernateCollectionIdResolver() {
}
@Override
public String idFromValue(Object value) {
//translate from HibernanteCollection class to JDK collection class
if (value instanceof PersistentArrayHolder) {
return Array.class.getName();
} else if (value instanceof PersistentBag || value instanceof PersistentIdentifierBag || value instanceof PersistentList) {
return List.class.getName();
} else if (value instanceof PersistentSortedMap) {
return TreeMap.class.getName();
} else if (value instanceof PersistentSortedSet) {
return TreeSet.class.getName();
} else if (value instanceof PersistentMap) {
return HashMap.class.getName();
} else if (value instanceof PersistentSet) {
return HashSet.class.getName();
} else {
//default is JDK collection
return value.getClass().getName();
}
}
@Override
public String idFromValueAndType(Object value, Class<?> suggestedType) {
return idFromValue(value);
}
//deserialize the json annotated JDK collection class name to JavaType
@Override
public JavaType typeFromId(DatabindContext ctx, String id) throws IOException {
try {
return ctx.getConfig().constructType(Class.forName(id));
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException(e);
}
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CLASS;
}
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS
)
@JsonTypeIdResolver(value = HibernateCollectionIdResolver.class)
public class HibernateCollectionMixIn {
}
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new JodaModule());
mapper.addMixIn(Collection.class, HibernateCollectionMixIn.class);
jackson2JsonRedisSerializer.setObjectMapper(mapper);