我有两个实体通过双向的一对一协会连接起来,就像这样:
@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关系变得懒惰
感谢您的帮助
1条答案
按热度按时间scyqe7ek1#
@onetooneMap就是这样。我去过那里,做到了。为了克服这一点,您必须在hibernate脏检查机制上实现字节码增强,并将父端更改为不使用代理(注解:@lazytoone(lazytooneoption.no\u proxy))。
请参考弗拉德·米哈尔恰的文章,我认为这篇文章准确地描述了你的情况
在那篇文章中,你还可以找到一个链接,链接到一篇有用的vlad文章,这篇文章是关于如何实现字节码增强的信息