Spring boot sprng启动jpa+;redis LazyInitializationException

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

我使用SpringBoot2.1.2和redis作为缓存提供程序

但是现在,我有一个问题

  • 在sysUser实体中
  • redis配置
  • 其他 我尝试这些方法

  • @JsonIgnore
    ,但它将设置
    角色
    ,我想使用此字段

  • 配置jackson registerModule
    Hibernate5模块
    ,它将设置
    角色
    null

  • 使用代理(lazy=false),不做任何更改

  • 使用
    @ManyToMany(fetch=FetchType.EAGER)
    ,不做任何更改

  • 配置

  • 没有变化

  • 使用其他json工具,如gson和FastJson,但在保存缓存时,jpa使用无限循环
  • 请帮帮我,我已经花了三天时间…但我没有解决这个问题

    谢谢

    github地址:


    如果没有解决方法,也许我必须使用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);