如何防止hibernate创建代理

时间:2017-05-26 08:54:43

标签: 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;
}

儿童

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为父字段创建代理。

感谢。

1 个答案:

答案 0 :(得分:0)

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

根据提供的映射,您无法忽略该字段,因为您将忽略ParentChild的信息。因此,通过这种设置,您始终需要阅读parent

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