java双向onetoone被多次加载

lg40wkob  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(482)

我有两个实体通过双向的一对一协会连接起来,就像这样:

@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数据和crudepository来使用生成的查询(如 Parent findByBusinessKey(String businessKey) 因为默认的fetchmode是eager,所以子实体通过其 child_id 父表中的外键。急切的抓取在这里不是问题,因为整个图形稍后会被序列化为json。
最初,这种联系是单向的,孩子与父母没有联系。不幸的是,必须添加back引用,性能严重下降。生成的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毫秒。通过单向Map,整个实体图的查询时间不到100毫秒。

问题

如何告诉hibernate父实体已经存在,不需要获取?我试过了 optional=false 但没用。

版本

我目前正在使用Hibernate5.2.12和SpringBoot1.2.8。不幸的是,版本更新目前不是一个选项。而且,即使db端的更改仍然是可能的,也需要在其他地方进行相对较大的重构工作。我只需要告诉hibernate不要急于从db获取父引用。也许一个entitygraph可以帮上忙,但我还没有用过,现在也没怎么用了。

另请参见

https://vladmihalcea.com/hibernate-facts-the-importance-of-fetch-strategy (结论部分提到了可选属性,但本例中的拥有方与我的情况相反)
如果定义了双向关系,hibernate将执行两次相同的查询
使用主键联接列的一对一Map
我怎样才能使一个jpa onetoone关系变得懒惰
感谢您的帮助

scyqe7ek

scyqe7ek1#

@onetooneMap就是这样。我去过那里,做到了。为了克服这一点,您必须在hibernate脏检查机制上实现字节码增强,并将父端更改为不使用代理(注解:@lazytoone(lazytooneoption.no\u proxy))。
请参考弗拉德·米哈尔恰的文章,我认为这篇文章准确地描述了你的情况
在那篇文章中,你还可以找到一个链接,链接到一篇有用的vlad文章,这篇文章是关于如何实现字节码增强的信息

相关问题