两个具有一对多关系的实体。
实体A指向实体B的列表,列表最多为几个。实体B反向引用了A。
当显示为JSON时,我希望看到A带有多个B或B带有对应的A。但这似乎取决于@OneToMany或@ManyToOne批注中的提取策略。
我读过的大多数东西都说@ManyToOne应该是LAZY,而@OneToMany应该是EAGER。这种方法将在列出实体A时起作用; JSON中显示了每个A及其关联的B。
但是在列出B时,出现错误
类型定义错误:[简单类型,类 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor];嵌套的 例外是 com.fasterxml.jackson.databind.exc.InvalidDefinitionException:否 找到用于类的序列化器 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor且不 发现的用于创建BeanSerializer的属性(为避免出现异常, 禁用SerializationFeature.FAIL_ON_EMPTY_BEANS
将LAZY更改为EAGER可解决此问题。但是,对于LAZY,我希望它至少能带来B记录。错误是令人惊讶的。
我将添加两个实体定义都使用JsonIdentityInfo(为防止无限递归而添加),它使用了SimpleObjectIdResolver。
因此,总而言之,我感到困惑。我可以使它“起作用”,但不确定为什么。
答案 0 :(得分:0)
我读过的大多数东西都说
@ManyToOne
应该是LAZY,而@OneToMany
应该是EAGER。这种方法将在列出实体A时起作用; JSON中显示了每个A及其关联的B。
这不是应该执行的操作,而是默认操作。可以在@ManyToOne
-和@OneToMany
文档中看到。各个用例之间应采取的措施各不相同。
作为例外:如果使用延迟加载定义了关系,则将插入代理对象,并在需要时从数据库中获取真实实体。 Jackson尝试序列化代理,但失败。这暗示了一个更深层次的架构设计缺陷:为什么要尝试序列化数据库实体?数据库和序列化过程(例如,通过DTO
转换)之间应该至少有一层。
即使序列化可以按预期进行(即,丢失的实体已被提取),加载实体的事务也很可能已经关闭,并且该过程将导致LazyInitializationException
。如果您预先知道始终需要获取关系,请使其热切获取。如果仅在某些情况下需要获取关系,请在JPQL中对获取进行编码,如有必要,可以在本机查询中对CriteriaQuery进行编码。提取延迟加载的@OneToMany
关系将导致N+1 problem,不惜一切代价避免。