我有一个棘手的问题,hibernate使用的查询比简单的findAll调用所需的查询多。在我的模型中,有两个实体Parent和Child具有oneToMany关联;
父
class Parent{
@id
private long id;
//unique
private String code;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<OperatorAttribute> children;
}
儿童
class Child{
@id
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_code", referencedColumnName = "code")
@LazyToOne(LazyToOneOption.NO_PROXY) // here i'm trying to tell hibernate to create no proxy and just ignore the field but no luck :/
public Parent parent;
}
问题是每当我尝试从数据库中使用childRepository.findAll()
获取子列表时,hibernate会进行N + 1选择查询,为什么?
我认为这可能是对此的解释:恕我直言Hibernate填充子对象时,他试图为父字段创建代理,
为此,他需要父行的id,通常应该是子表中的外键,但在我的情况下,#fk
没有绑定到Parent
表的主键但是为了一个独特的列(plz不要问我为什么)所以为了填充id他需要做一个额外的select查询来初始化父字段的代理。
所以我的问题是如何防止Hibernate为父字段创建代理。
感谢。
答案 0 :(得分:0)
你是对的。代理需要代理实体的@Id
(这样可以确保它可以找到)。一旦定义LazyToOneOption.NO_PROXY
,它就会告诉系统give back the real object。这就是这里发生的事情。您在结果上映射的内容不是代理,因为使用此批注您明确禁用它,因此您必须获取真实对象。
根据提供的映射,您无法忽略该字段,因为您将忽略Parent
上Child
的信息。因此,通过这种设置,您始终需要阅读parent
。
如果特定区域根本不需要此字段,则可以为同一个表创建一些其他映射。不过要小心!这可能会引入大量其他与缓存相关的问题。