Hibernate не использует пакетную обработку при двунаправленной связи OneToMany с JoinTable

У меня есть несколько сущностей с двунаправленным @OneToMany-отношением с @JoinTable. Функциональность работает нормально, кроме производительности вставки большого количества наборов данных в базу данных. Я обнаружил, что в этом случае Hibernate не использует пакетную обработку для всех сущностей. Спящий режим с использованием пакетной обработки для родительских сущностей, но не для дочерних. Он вставляет все родительские наборы данных в базу данных с помощью пакетной обработки, но затем генерирует дочерний набор данных, затем связанный набор данных mappingtable, затем следующий набор дочерних данных, затем связанный набор данных mappingtable-dat и т. Д., Все с одним заявления.

Когда я изменяю @OneToMany-Relation для теста на @ManyToMany-Relation, то пакетная обработка используется для всех наборов данных, сначала всех родителей, затем всех потомков, затем всех отображений и производительность резко возрастает. Также на однонаправленной пакетной обработке OneToMany-Relation работает нормально.

Может кто-нибудь объяснить мне, как настроить двунаправленное @OneToMany-отношение с @JoinTable, чтобы Hibernate также использовал пакетную обработку для детей?

Простой пример для воспроизведения: родитель A:

package com.flobuc;

import javax.persistence.*;
import java.util.Collection;

@Entity
@Table(name = "A")
public class A {
    private String id;
    private String name;
    private Collection<B> bs;

    @Id
    @Column(name = "ID")
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Basic
    @Column(name = "NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    @OneToMany(cascade = CascadeType.ALL, mappedBy = "a")
    public Collection<B> getBs() {
        return bs;
    }

    public void setBs(Collection<B> bs) {
        this.bs = bs;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        A a = (A) o;

        if (id != null ? !id.equals(a.id) : a.id != null) return false;
        return name != null ? name.equals(a.name) : a.name == null;
    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}

Ребенок Б:

package com.flobuc;

import javax.persistence.*;

@Entity
@Table(name = "B")
public class B {
    private String id;
    private String name;
    private A a;

    @Id
    @Column(name = "ID")
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Basic
    @Column(name = "NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne
    @JoinTable(
            name="A2B",
            joinColumns = {@JoinColumn(name = "B_ID", referencedColumnName = "ID", nullable = false)},
            inverseJoinColumns={@JoinColumn(name = "A_ID", referencedColumnName = "ID", nullable = false)})
    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        B b = (B) o;

        if (id != null ? !id.equals(b.id) : b.id != null) return false;
        return name != null ? name.equals(b.name) : b.name == null;
    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}

Создавайте сущности и сохраняйте:

List<A> as = new ArrayList<>();

for (int i = 0; i < 100 ; i++) {

    A a = new A();
    a.setId("ID-A-" + i);
    a.setName("Name ID-" + i);

    a.setBs(new HashSet<>());

    for (int j = 0; j < 50 ; j++) {
        B b =new B();
        b.setId("ID-B-" + j + "ID-A-" + i);
        b.setName("Name ID-" + j + " Parent " + i);
        b.setA(a);
        a.getBs().add(b);
    }

    as.add(a);

}

for(A a : as){
    em.persist(a);
}

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                                 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="TimetablePU" transaction-type="JTA">

        <jta-data-source>java:/TimetableDS</jta-data-source>
        <class>com.atron.atries.rx.asdm.dao.entity.netex.A</class>
        <class>com.atron.atries.rx.asdm.dao.entity.netex.B</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
            <property name="hibernate.jdbc.batch_size" value="10"/>
            <property name="hibernate.order_inserts" value="true"/>
            <property name="hibernate.order_updates" value="true"/>
            <property name="hibernate.jdbc.batch_versioned_data" value="true"/>                
        </properties>

    </persistence-unit>

</persistence>

Конверт: WildFly 10.1, Hibernate 5.0.1

0 ответов

Другие вопросы по тегам