java - 如何防止hibernate创建代理

标签 java hibernate proxy

我在 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;
}

child

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,该 id 通常应该是子表中的外键,但在我的情况下,#fk 并未绑定(bind)到 Parent 表的主键,而是绑定(bind)到一个唯一列(请不要问我为什么),因此为了填充 id,他需要执行额外的选择查询来初始化父字段的代理。

所以我的问题是如何阻止 Hibernate 为父字段创建代理。

谢谢。

最佳答案

你是对的。代理需要被代理实体的@Id(这样可以确保可以找到它)。一旦定义了LazyToOneOption.NO_PROXY,它就会告诉系统 give back the real object 。这就是这里发生的事情。您在结果上映射的不是代理,因为使用此注释您显式禁用了它,因此您必须获取真实的对象。

根据所提供的映射,您不能忽略该字段,因为您将丢失 Child 上的 Parent 的信息。因此,通过这种设置,您始终需要读取父级

如果在特定区域中根本不需要此字段,您可以创建一些到同一表的其他映射。不过要小心!这可能会引入大量其他与缓存相关的问题。

关于java - 如何防止hibernate创建代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44197466/

相关文章:

java - ManyToOne 关系上的 Hibernate @Where 注释

http - HTTP 代理缓存如何决定服务身份编码资源还是 gzip 编码资源?

java - 当参数类型在 postgresql 中是 "timestamp without time zone"时,Java 中的参数类型应该是什么?

java - JPA、继承和instanceof

java - Spring Hibernate 集成错误

proxy - 如何检测 VPN 或代理连接?

http - 使用 Squid 按需将文本附加到 HTTP 响应

java - 运行集成测试 EJB 时出现问题

java - 从用于 Google map 标记的 SQLite 数据库中读取值

java - Android MapView 类未找到