【问题标题】:Spring Boot, many to one relationship fetch LAZY or EAGERSpring Boot,多对一关系获取 LAZY 或 EAGER
【发布时间】:2019-11-03 07:49:13
【问题描述】:

具有双向一对多关系的两个实体。

实体 A 指向实体 B 的列表,最多有几个。实体 B 具有对 A 的反向引用。

当显示为 JSON 时,我希望看到带有多个 B 的 A 或带有相应 A 的 B。但这似乎取决于 @OneToMany 或 @ManyToOne 注释中的获取策略。

我读过的大部分内容都说@ManyToOne 应该是 LAZY,@OneToMany 应该是 EAGER。该方法将在实体 A 上市时奏效;每个 A 及其关联的 B 都以 JSON 格式显示。

但是当列出 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。

所以,总而言之,我很困惑。我可以让它“工作”,但不确定为什么。

【问题讨论】:

  • 查看这个post,其中设置hibernate.enable_lazy_load_no_trans=true用于防止懒惰问题

标签: java json hibernate spring-boot


【解决方案1】:

我读过的大部分内容都说@ManyToOne 应该是 LAZY,@OneToMany 应该是 EAGER。该方法将在实体 A 上市时奏效;每个 A 及其关联的 B 都以 JSON 格式显示。

这不是应该做的,而是默认的。这可以在 @ManyToOne- 和 @OneToMany- 文档中看到。应该做什么因用例而异。


例外:如果使用延迟加载定义关系,则插入代理对象,并在需要时从数据库中获取真实实体。 Jackson 尝试序列化代理但失败了。这暗示了一个更深层次的架构设计缺陷:你为什么要序列化一个数据库实体?数据库和序列化过程之间应该至少有一层(例如,通过DTO 转换)。

即使序列化按预期工作(即获取丢失的实体),加载实体的事务很可能已经关闭,并且该过程将导致LazyInitializationException。如果您事先知道您总是需要获取关系,请急切地获取它。如果您只需要在某些情况下获取关系,请在 JPQL 中对获取进行编码,如有必要,在本机查询中使用 CriteriaQuery。获取延迟加载的@OneToMany 关系将导致N+1 problem,应不惜一切代价避免这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-06
    • 2020-05-28
    • 1970-01-01
    • 2019-01-24
    • 2023-03-03
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多