Выборочное соединение вызывает N + 1 запросов или бросает org.hibernate.QueryException - PullRequest
2 голосов
/ 11 июля 2019

Я пытаюсь получить один список запросов объектов и его ассоциаций, к сожалению, либо я вызываю N + 1 запросов к базе данных, либо получаю исключение "org.hibernate.QueryException: в запросе указывается соединение, извлекаемое, но владелецизвлеченной ассоциации не было в списке выбора ".

Пожалуйста, позвольте мне рассказать вам о моем случае.

Ниже приведена моя модель данных:

@Table(name = "first_table")
public class FirstObject {
    @Id
    @Column(nullable = false, name = "first_id")
    private Long id;

    @Column(nullable = false, name = "first_param")
    private String param1;

    @ManyToOne
    @JoinColumn(nullable = false, name = "second_id")
    private SecondObject second;

    ...other columns...
}

@Table(name = "second_table")
public class SecondObject {
    @Id
    @Column(nullable = false, name = "second_id")
    private Long id;

    @Column(nullable = false, name = "second_param")
    private Long param2;

    @ManyToOne
    @JoinColumn(nullable = false, name = "third_id")
    private ThirdObject third;

    ...other columns...
}

@Table(name = "third_table")
public class ThirdObject {
    @Id
    @Column(nullable = false, name = "third_id")
    private Long id;

    ...other columns...
}

Это верно для отношений с базой данных, в том числе и так, как я этого хочуFE.Все, чего я пытаюсь добиться, - это получить все ассоциации одним запросом, выдав 2 условия:

ConditionBuilder condition = new ConditionBuilder()
            .and(FirstObject.second.param2.eq(some_number))
            .and(FirstObject.param1.eq(some_string));

    return from(FirstObject)
            .join(FirstObject.second).fetchJoin()
            .join(FirstObject.second.third).fetchJoin()
            .where(condition.generate())
            .fetch();

К сожалению, этот код вызывает исключение:

org.hibernate.QueryException:в запросе указано соединение выборки, но владелец выбранной ассоциации не присутствует в списке выбора

Я могу заставить его работать, но с N + 1 запросами, но это приемлемо только на этапе разработки,что вызовет проблему с производительностью.

...
.join(FirstObject.second).fetchJoin()
.join(FirstObject.second.third)
...

то же самое здесь:

...
.join(FirstObject.second)
.join(FirstObject.second.third)
...

Я пытаюсь выяснить, как сделать режим гибернации для создания одного простого запроса, подобного этому:

select
    *
from
    first_table table1 
inner join
    second_table table2 
        on table1.second_id=table2.second_id 
inner join
    third_table table3 
        on table2.third_id=table3.third_id 
where
    table1.first_param="some_string"
    table2.second_param=some_number

Вся помощь очень ценится, я боролся с этим в течение некоторого времени и действительно рассчитываю на сообщество.Большое спасибо.

1 Ответ

0 голосов
/ 11 июля 2019

Вы должны отобразить обе стороны отношения сущности:

например, в FirstObject у вас есть это:

@ManyToOne
@JoinColumn(nullable = false, name = "second_id")
private SecondObject second;

Так что в SecondObject вы должны иметь это:

@OneToMany(mappedBy = "second") // this is the name of the field in the class that defines the join relationship
Collection<FirstObject> firstObjects;

В ThirdObject вы должны иметь это:

@OneToMany(mappedBy = "third") // this is the name of the field in the class that defines the join relationship
Collection<SecondObject> secondObjects;
...