【问题标题】:Bidirectional OneToOne gets Loaded multiple Times双向 OneToOne 被多次加载
【发布时间】:2021-03-26 04:23:52
【问题描述】:

我有两个通过双向 OneToOne 关联连接的实体,如下所示:

@Entity
class Parent {

    @NotNull
    String businessKey;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "child_id")
    @JsonManagedReference
    Child child;

}

@Entity
class Child {

  @JsonBackReference
  @OneToOne(mappedBy = "child", fetch = FetchType.LAZY)
  Parent parent;

}

背景

我正在使用 Spring Data 和 CRUDRepository 使用生成的查询(如 Parent findByBusinessKey(String businessKey))加载父级 因为默认的 FetchMode 是 Eager,所以子实体通过父表中的 child_id 外键获取。 Eager fetching 在这里不是问题,因为整个图稍后会被序列化为 json。

最初该关联是单向的,并且 Child 没有引用其 Parent。不幸的是,必须添加反向引用并且性能极度下降。生成的 Sql 的日志显示以下查询(简化):

select p.id, p.business_key, ..., p.child_id from Parent p where p.business_key = ?;


select c.id, ... from Child c where c.id = ?;

-- here it goes wrong
select p.id, p.business_key, ... from Parent p
   left join OtherEagerJoinedTable t on p.other_id = t.id
   left join AnotherEagerJoinedTable a on p.another_id = a.id
 where p.child_id = ?;

Hibernate 似乎从数据库中单独获取父对象,而不是使用已经选择的实例。对于每个像这样的 OneToOne 关系(有几个)都会发生这种情况,每个连接查询最多需要 200 毫秒。通过单向映射,整个实体图的查询时间不到 100 毫秒。

问题

我如何告诉 Hibernate 父实体已经存在并且不需要获取?我在子实体中尝试了optional=false,但没有帮助。

版本

我目前使用的是休眠 5.2.12 和 Spring Boot 1.2.8。不幸的是,版本更新目前不是一个选项。此外,即使 DB 端的更改仍然可能,它也需要在其他地方进行相对较大的重构工作。 我只需要告诉 hibernate 不要急于从 Db 获取父引用。也许 EntityGraph 可以帮助解决这个问题,但我还没有使用它们,现在也没有太多。

另见

感谢任何帮助

【问题讨论】:

  • 你没有提供足够的上下文。
  • 您可以尝试添加@JsonManagedReference@JsonBackReference
  • @SSK 这些已经存在于我的实际代码中,我在示例中添加了它们以澄清

标签: java spring-boot hibernate jpa one-to-one


【解决方案1】:

@OneToOne 映射就是这种情况。我去过那里,做到了。要解决这个问题,您必须在 Hibernate 脏检查机制上实现字节码增强,并更改父端不使用代理(注解:@LazyToOne(LazyToOneOption.NO_PROXY))。

请参考Vlad Mihalcea's article describing exactly your case I think

在那篇文章中,您还将找到另一个有用的 Vlad 文章的链接 - 有关如何实现字节码增强的信息

【讨论】:

  • 我也偶然发现了这篇文章,但我认为我可以通过正确的注释来解决这个问题。但我想我试试字节码版本,看看它是否有效
  • 字节码增强对我有用,但缺点是需要 maven 编译而不是更快的 Intellij 内置编译器(至少对于本地开发)
猜你喜欢
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 2012-10-14
  • 1970-01-01
  • 2021-07-14
  • 2013-08-19
  • 1970-01-01
相关资源
最近更新 更多