【问题标题】:How to get rid of a N+1 query on Hibernate/JPA updating children rows with their parent ID如何摆脱 Hibernate/JPA 上的 N+1 查询,用父 ID 更新子行
【发布时间】:2017-01-18 02:39:53
【问题描述】:

我正在解决一些性能问题,我注意到 hibernate 正在生成 N+1 个查询来更新子实体中的父 id。

我正在使用Spring 4.3.4Hibernate 5.2.5Spring Data 1.10.5

我有这样的代码:

Parent p = createParent();
Parent savedParent = parentRepo.save(p);
savedParent.addChild(new Child());
savedParent.addChild(new Child());
savedParent.addChild(new Child());
parentRepo.save(savedParent);

问题是它生成这样的sql:

insert into parent (col1, col2, col3) values (1,2,3)
insert into child (col1, col2, col3, parent_id) values (1,2,3, PARENT_ID), (1,2,3, PARENT_ID), (1,2,3, PARENT_ID)
update child set parent_id = PARENT_ID where id = x
update child set parent_id = PARENT_ID where id = x+1
update child set parent_id = PARENT_ID where id = x+2

我的映射是这样的

Parent{
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "parent_id", nullable = false)
    @BatchSize(size = 500)
    private List<Child> items;
}

Child{
    @ManyToOne(optional = false)
    @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false, insertable= false, updatable = false)
    private Parent parent;
}

我尝试过先保存父级以确保它在添加子级之前有一个 id,并且在不先保存父级的情况下进行一次大规模保存,但它总是会生成 N+1 查询。我已经确保我在代码中设置了孩子的清单,只是为了确保它知道它是父母,但这似乎也没有帮助。我所有的谷歌搜索都涉及如何防止大多数类型的 N+1 查询,但不是这种特定类型。这很奇怪,因为它在插入中正确设置了父 ID,但随后感觉需要更新它,即使它没有改变。

【问题讨论】:

  • 它怎么知道base id值?!!

标签: java mysql spring hibernate jpa


【解决方案1】:

请尝试以下我添加了 mappedBy 属性的代码。这是您在对象图中设置但未反映在休眠关系中的简单双向映射的情况。

Parent{
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true,mappedBy="parent")
@JoinColumn(name = "parent_id", nullable = false)
@BatchSize(size = 500)
private List<Child> items;
}

【讨论】:

    【解决方案2】:

    我得到了它的工作,我不得不将我的映射更改为:

    Parent{
        @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "parent")
        @BatchSize(size = 500)
        private List<Child> items;
    }
    
    Child{
        @ManyToOne(optional = false)
        @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false)
        private Parent parent;
    }
    

    然后一切正常

    【讨论】:

    • 如果你能接受我的回答,如果它有帮助,那就太好了:)
    猜你喜欢
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2017-10-07
    相关资源
    最近更新 更多