在做的我的项目采纳的是spring jpa,底层默认应用的是orm是hibernate,通过hibernate查问进去的实体对象实际上都是代理对象,在序列化的时候,咱们可能会遇到懒加载导致jackson无奈正确解析对象的问题,这个能够通过导入maven包
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-hibernate5</artifactId></dependency>
而后加载进objectMapper上下文
@Beanpublic Jackson2ObjectMapperBuilderCustomizer builderCustomizer() { return builder -> { //jackson序列化 和 hibernate懒加载 builder.modulesToInstall(hibernate5Module()); };}private static Hibernate5Module hibernate5Module() { Hibernate5Module hibernate5Module = new Hibernate5Module(); hibernate5Module.configure(REPLACE_PERSISTENT_COLLECTIONS, true); //hibernate5Module.configure(FORCE_LAZY_LOADING, true); return hibernate5Module;}
这样在序列化的时候就会判断之前是否存在数据了,如果是懒加载则会序列化为null。
我在反序列化的时候会报failed to lazily initialize a collection, could not initialize proxy...,起初看了一下序列化后的json,发现有些提早加载的Collection类型的会解析成org.hibernate.collection.internal.PersistentBag(hibernate的代理对象),而不是咱们个别json的汇合模式。导致反序列化的时候,会生成PersistentBag对象,这时候jackson操作PersistentBag,会导致hibernate检测到数据变动,从而触发它的一些操作而报下面的错。
而后我就排查,为啥序列化的时候会转成PersistentBag对象呢?能够看看Hibernate5Module里的代码,该模块会加载两个
context.addSerializers(new HibernateSerializers(_mapping, _moduleFeatures));context.addBeanSerializerModifier(new HibernateSerializerModifier(_moduleFeatures, _sessionFactory));//序列化处理器,咱们之前的解决懒加载原理也是通过这两个解决的,而后我在HibernateSerializerModifier里看到了PersistentCollectionSerializer,对于汇合类型的解析解决,其中次要有个判断办法protected boolean usesLazyLoading(BeanProperty property) { if (property != null) { // As per [Issue#36] ElementCollection ec = property.getAnnotation(ElementCollection.class); if (ec != null) { return (ec.fetch() == FetchType.LAZY); } OneToMany ann1 = property.getAnnotation(OneToMany.class); if (ann1 != null) { return (ann1.fetch() == FetchType.LAZY); } OneToOne ann2 = property.getAnnotation(OneToOne.class); if (ann2 != null) { return (ann2.fetch() == FetchType.LAZY); } ManyToOne ann3 = property.getAnnotation(ManyToOne.class); if (ann3 != null) { return (ann3.fetch() == FetchType.LAZY); } ManyToMany ann4 = property.getAnnotation(ManyToMany.class); if (ann4 != null) { return (ann4.fetch() == FetchType.LAZY); } // As per [Issue#53] return !Feature.REQUIRE_EXPLICIT_LAZY_LOADING_MARKER.enabledIn(_features); } return false;}
发现我关联字段上应用的是@ManyToMany(fetch = FetchType.EAGER),因为我之前为了解决懒加载就加上的,当初能够去掉了,问题也失去了解决。