我有两个简单的类:
Cat
CatStore
Cat
没有什么特别的,而CatStore
有一个List<Cat>
,关系Map为:
在Cat
类中:
@ManyToOne
private CatStore catstore;
在CatStore
中:
@OneToMany(mappedBy="catstore", fetch=FetchType.EAGER)
private List<Cat> cats;
这个关系看起来工作正常,因为当我运行时,Jackson可以生成正确的JSON
String json = mapper.writeValueAsString(catStore);
但是如果我尝试反序列化我刚刚生成的JSON,使用这行:
CatStore c2 = mapper.readValue(json, CatStore.class);
我得到一个JsonProcessingException
说
failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: fr.truc.java.cleanspringbootMVC.model.CatStore["cats"]
如果CatStore
中没有cats,反序列化实际上可以工作,如下面的JSON:
{
"id":123,
"cats":["org.hibernate.collection.internal.PersistentBag",[]],
"name":"NO cats"
}
但这一个触发了错误:
{
"id": 121,
"cats": ["org.hibernate.collection.internal.PersistentBag", [
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 118,
"name": "luc",
"nbPattes": 4
}],
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 119,
"name": "andré",
"nbPattes": 4
}],
["fr.truc.java.cleanspringbootMVC.model.Cat", {
"id": 120,
"name": "cheval",
"nbPattes": 4
}]
]],
"name": "Cat en kit"
}
我真的不知道为什么延迟加载异常会在这里触发,因为数据包含在JSON字符串中。
这与PersistentBag有关吗?
这是因为我没有使用自定义序列化器/反序列化器吗?
3条答案
按热度按时间v7pvogib1#
如果使用JPA,所有实体都将通过字节码增强,以允许延迟加载等。它们实际上并不适合序列化,除了hibernate,hibernate意识到了这一点。但是Jackson并不知道这件事,所以它会破坏增强的字节码。
对于JPAMap和JacksonMap使用同一个类也不是一个好主意。JPA类具有Map到列等的字段,而Jackson的类Map到javascript模式。如果你在同一个类中使用它们,你永远无法在不影响JSON模式的情况下更改数据库模式,并且可能会破坏与使用JSON的人的向后兼容性。
最好有单独的类(DTO)用于Jackson,并在它们之间进行一些Map。或者使用mapstruct自动生成Map器。
flmtquvp2#
错误似乎与
mapper.enableDefaultTyping();
有关启用后,每个类的类型都以JSON输出。(我想要的)
由于某种原因,它会在@ManyToOne上导致上述错误
当禁用时,PersistentBag不再出现在我的序列化JSON中,并且反序列化工作...
s3fp2yjn3#
我也遇到了同样的问题。要在使用
enableDefaultTyping
(或当前推荐的activateDefaultTyping
)时修复它,我必须使用Hibernate5Module:(注意,所需的模块取决于您的hibernate版本,必须作为附加依赖项添加。)这会将输出中的
PersistentBag
替换为ArrayList
,并防止反序列化错误。然而,这个功能似乎不适用于
FetchType.EAGER
,原因我不知道。幸运的是,@Fetch(FetchMode.JOIN)
做到了这一点。另一件需要考虑的事情是,
REPLACE_PERSISTENT_COLLECTIONS
特性为我生成了格式错误的JSON(将列表内容 Package 在双方括号中)。但这是通过使用宽松的反序列化解决的。