Quantcast
Channel: Найцікавіше на DOU
Viewing all articles
Browse latest Browse all 8115

Стратегии загрузки коллекций в Hibernate

$
0
0

В предыдущей статьея рассматривал детали различных типов и стратегий загрузки коллекций в JPA. В данной статье будут рассмотрены режимы загрузки коллекций в Hibernate.

Для тех, кто не читал, повторюсь: отношениям один-ко-многим или многие-ко-многим между таблицами реляционной базы данных в объектном виде соответствуют свойства сущности типа Listили Set, размеченные аннотациями @OneToManyили @ManyToMany. При работе с сущностями, которые содержат коллекции других сущностей, возникает проблема известная как «N+1 selects». Первый запрос выберет только корневые сущности, а каждая связанная коллекция будет загружена отдельным запросом. Таким образом ORM выполняет N+1 SQL запросов, где N — количество корневых сущностей в результирующей выборке запроса.

Итак, самая популярная реализация JPA, Hibernate предоставляет множество способов управления загрузкой отношений один-ко-многим и многие-ко-многим.

FetchMode в Hibernate говорит как мы хотим, чтоб связанные сущности или коллекции были загружены:
— SELECT — используя по дополнительному SQL запросу на коллекцию,
— JOIN — в одном запросе с корневой сущностью, используя SQL оператор JOIN,
— SUBSELECT— в дополнительном запросе, используя SUBSELECT.

Мы также можем влиять на стратегию загрузки связанных коллекций при помощи аннотации @BatchSize (или атрибут batch-size в XML), которая устанавливает количество коллекций, которые будут загружаться в одном запросе.

Пример

Продолжим рассматривать пример из предыдущей части статьи, в котором сущность Book владеет отношениями многие-ко-многим с сущностями Authorи Category. Дополним этот пример, добавив аннотации из пакета org.hibernate.annotations, которые не являются частью JPA. Пример целиком доступен на Github.

@Entity
public class Book extends AbstractBook {

    @ManyToMany(fetch = FetchType.EAGER)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany
    private List<Category> categories = new ArrayList<>();

    /*...*/
}

@Entity
public class BookFetchModeSelect extends AbstractBook {

    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.SELECT)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany
    @Fetch(FetchMode.SELECT)
    private List<Category> categories = new ArrayList<>();

    /*...*/
}

@Entity
public class BookFetchModeJoin extends AbstractBook {

    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany
    @Fetch(FetchMode.JOIN)
    private List<Category> categories = new ArrayList<>();
    /*...*/
}

@Entity
public class BookFetchModeSubselect extends AbstractBook {

    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.SUBSELECT)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany
    @Fetch(FetchMode.SUBSELECT)
    private List<Category> categories = new ArrayList<>();

    /*...*/
}

@Entity
public class BookBatchSize extends AbstractBook {

    @ManyToMany(fetch = FetchType.EAGER)
    // Явное указание FetchMode.SELECT необходимо
    // так как в Criteria API EAGER ассоциации по умолчанию загружаются с
    @Fetch(FetchMode.SELECT)
    @BatchSize(size = 2)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany
    @Fetch(FetchMode.SELECT)
    @BatchSize(size = 2)
    private List<Category> categories = new ArrayList<>();
    /*...*/
}

Для более наглядной демонстрации отличий режимов загрузки необходимо добавить больше тестовых данных:

Session session = sessionFactory.getCurrentSession();

Category softwareDevelopment = new Category();
softwareDevelopment.setName("Software development");
session.persist(softwareDevelopment);

Category systemDesign = new Category();
systemDesign.setName("System design");
session.persist(systemDesign);

Author martinFowler = new Author();
martinFowler.setFullName("Martin Fowler");
session.persist(martinFowler);

AbstractBook poeaa = bookSupplier.get();
poeaa.setIsbn("007-6092019909");
poeaa.setTitle("Patterns of Enterprise Application Architecture");
poeaa.setPublicationDate(Date.from(Instant.parse("2002-11-15T00:00:00.00Z")));
poeaa.setAuthors(asList(martinFowler));
poeaa.setCategories(asList(softwareDevelopment, systemDesign));
session.persist(poeaa);

Author gregorHohpe = new Author();
gregorHohpe.setFullName("Gregor Hohpe");
session.persist(gregorHohpe);

Author bobbyWoolf = new Author();
bobbyWoolf.setFullName("Bobby Woolf");
session.persist(bobbyWoolf);

AbstractBook eip = bookSupplier.get();
eip.setIsbn("978-0321200686");
eip.setTitle("Enterprise Integration Patterns");
eip.setPublicationDate(Date.from(Instant.parse("2003-10-20T00:00:00.00Z")));
eip.setAuthors(asList(gregorHohpe, bobbyWoolf));
eip.setCategories(asList(softwareDevelopment, systemDesign));
session.persist(eip);

Category objectOrientedSoftwareDesign = new Category();
objectOrientedSoftwareDesign.setName("Object-Oriented Software Design");
session.persist(objectOrientedSoftwareDesign);

Author ericEvans = new Author();
ericEvans.setFullName("Eric Evans");
session.persist(ericEvans);

AbstractBook ddd = bookSupplier.get();
ddd.setIsbn("860-1404361814");
ddd.setTitle("Domain-Driven Design: Tackling Complexity in the Heart of Software");
ddd.setPublicationDate(Date.from(Instant.parse("2003-08-01T00:00:00.00Z")));
ddd.setAuthors(asList(ericEvans));
ddd.setCategories(asList(softwareDevelopment, systemDesign, objectOrientedSoftwareDesign));
session.persist(ddd);

Category networkingCloudComputing = new Category();
networkingCloudComputing.setName("Networking & Cloud Computing");
session.persist(networkingCloudComputing);

Category databasesBigData = new Category();
databasesBigData.setName("Databases & Big Data");
session.persist(databasesBigData);

Author pramodSadalage = new Author();
pramodSadalage.setFullName("Pramod J. Sadalage");
session.persist(pramodSadalage);

AbstractBook nosql = bookSupplier.get();
nosql.setIsbn("978-0321826626");
nosql.setTitle("NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence");
nosql.setPublicationDate(Date.from(Instant.parse("2012-08-18T00:00:00.00Z")));
nosql.setAuthors(asList(pramodSadalage, martinFowler));
nosql.setCategories(asList(networkingCloudComputing, databasesBigData));
session.persist(nosql);

В тестах используется Hibernate 5.2.0.Final.

HQL запрос и FetchMode по умолчанию

Когда аннотация @Fetch не добавлена, HQL и Hibernate Criteria запросы ведут себя по-разному. В случае использования HQL запроса, по умолчанию используется FetchMode.SELECTдля связанных коллекций с любым типом загрузки (EAGERи LAZY).

List books = getCurrentSession().createQuery("select b from Book b").list(); 
assertEquals(4, books.size());

Сгенерированный SQL:

select
        book0_.id as id1_1_,
        book0_.isbn as isbn2_1_,
        book0_.publicationDate as publicat3_1_,
        book0_.title as title4_1_
    from
        Book book0_

select
    authors0_.Book_id as Book_id1_2_0_,
    authors0_.authors_id as authors_2_2_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    Book_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.Book_id=?

select
    authors0_.Book_id as Book_id1_2_0_,
    authors0_.authors_id as authors_2_2_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    Book_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.Book_id=?

select
    authors0_.Book_id as Book_id1_2_0_,
    authors0_.authors_id as authors_2_2_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    Book_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.Book_id=?

select
    authors0_.Book_id as Book_id1_2_0_,
    authors0_.authors_id as authors_2_2_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    Book_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.Book_id=?

Hibernate Criteria запрос и FetchMode по умолчанию

Когда аннотация @Fetch не добавлена, в Hibernate Criteria запросах по умолчанию используется FetchMode.JOINдля связанных коллекций с типом загрузки EAGERи tchMode.SELECTдля связанных коллекций с типом загрузки LAZY.

Коллекции с типом загрузки EAGERбудут загружены в одном SQL запросе с корневой сущностью. Результатом запроса будет декартово произведение (cartesian product). Вместо 4 элементов в результирующей выборке, запрос вернет 6, потому что книги «Enterprise Integration Patterns» и «NoSQL» имеют двух авторов и будут дважды встречаться в результатах запроса.

Стоит отметить, что начиная с версии Hibernate 5.2 метод createCriteriaкласса org.hibernate.Session, который создает экземпляр org.hibernate.Criteria, считает устаревшим и помечен аннотацией @Deprecated. Вместо этого в Javadocрекомендуется использовать JPA Criteria.

List books = getCurrentSession().createCriteria(Book.class).list(); 
assertEquals(6, books.size());

Сгенерированный SQL:

select
    this_.id as id1_1_1_,
    this_.isbn as isbn2_1_1_,
    this_.publicationDate as publicat3_1_1_,
    this_.title as title4_1_1_,
    authors2_.Book_id as Book_id1_2_3_,
    author3_.id as authors_2_2_3_,
    author3_.id as id1_0_0_,
    author3_.fullName as fullName2_0_0_ 
from
    Book this_ 
left outer join
    Book_Author authors2_ 
        on this_.id=authors2_.Book_id 
left outer join
    Author author3_ 
        on authors2_.authors_id=author3_.id

HQL и Hibernate Criteria запросы и FetchMode.SELECT

С режимом загрузки FetchMode.SELECTпервый запрос выберет только корневые сущности, а каждая связанная коллекция будет загружена отдельным запросом. Так как для данного примера мы сохранили 4 сущности, то запросов будет 5. Один для загрузки сущностей Bookи по одному для каждой из 4 сущностей Bookдля загрузки списка сущностей Author. Список сущностей Categoryимеет тип загрузки по умолчанию (LAZYдля коллекций) и будет загружен отдельным запросом при первом обращении в коде.

List books = getCurrentSession().createQuery("select b from BookFetchModeSelect b").list();
assertEquals(4, books.size());

При режиме загрузки FetchMode.SELECT HQL и Hibernate Criteria запросы ведут себя одинаково.

List books = getCurrentSession().createCriteria(BookFetchModeSelect.class).list(); 
assertEquals(4, books.size());

Сгенерированный SQL:

select
    bookfetchm0_.id as id1_10_,
    bookfetchm0_.isbn as isbn2_10_,
    bookfetchm0_.publicationDate as publicat3_10_,
    bookfetchm0_.title as title4_10_
from
    BookFetchModeSelect bookfetchm0_

select
    authors0_.BookFetchModeSelect_id as BookFetc1_11_0_,
    authors0_.authors_id as authors_2_11_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeSelect_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeSelect_id=?
 
select
    authors0_.BookFetchModeSelect_id as BookFetc1_11_0_,
    authors0_.authors_id as authors_2_11_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeSelect_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeSelect_id=?

select
    authors0_.BookFetchModeSelect_id as BookFetc1_11_0_,
    authors0_.authors_id as authors_2_11_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeSelect_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeSelect_id=?
 
select
    authors0_.BookFetchModeSelect_id as BookFetc1_11_0_,
    authors0_.authors_id as authors_2_11_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeSelect_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeSelect_id=?<pre><h2>HQL и Hibernate Criteria запросы и FetchMode.SUBSELECT</h2>

При режиме загрузки <code>FetchMode.SUBSELECT</code> будет выполнено 2 SQL запроса. Первый загрузит корневые сущности, а второй - связанные коллекции для всех корневых сущностей из результатов первого SQL запроса, используя подзапрос.

<pre>List books = getCurrentSession().createQuery("select b from BookFetchModeSubselect b").list();
assertEquals(4, books.size());

HQL и Hibernate Criteria запросы ведут себя одинаково и при режиме загрузки FetchMode.SUBSELECT.

List books = getCurrentSession().createCriteria(BookFetchModeSubselect.class).list();
assertEquals(4, books.size());

Сгенерированный SQL:

select
    bookfetchm0_.id as id1_13_,
    bookfetchm0_.isbn as isbn2_13_,
    bookfetchm0_.publicationDate as publicat3_13_,
    bookfetchm0_.title as title4_13_
from
    BookFetchModeSubselect bookfetchm0_

select
    authors0_.BookFetchModeSubselect_id as BookFetc1_14_1_,
    authors0_.authors_id as authors_2_14_1_,
    author1_.id as id1_0_0_,
    author1_.fullName as fullName2_0_0_
from
    BookFetchModeSubselect_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeSubselect_id in (
        select
            bookfetchm0_.id
        from
            BookFetchModeSubselect bookfetchm0_
    )

HQL запрос и FetchMode.JOIN

Поведение HQL запросов при режиме загрузке FetchMode.JOIN, на первый взгляд, немного неожиданное. Вместо того, чтобы загрузить связанные коллекции, помеченные аннотацией @Fetch(FetchMode.JOIN), в одном запросе с корневыми сущностями, используя SQL оператор JOIN, HQL запрос транслируется в несколько SQL запросов по типа FetchMode.SELECT. Но в отличии от FetchMode.SELECT, при FetchMode.JOINбудет игнорироваться указанный тип загрузки (LAZYи EAGER) и все коллекции будут загружены сразу, а не при первом обращении в коде (поведение соответствующее типу EAGER).

Таким образом в следующем примере будет выполнено 8 SQL запросов. Один запрос для загрузки корневых сущностей Bookи для каждой из 4 корневых сущностей из результатов первого SQL запроса по одному запросу для загрузки списка сущностей Authorи по одному запросу для загрузки списка сущностей Category.

List books = getCurrentSession().createQuery("select b from BookFetchModeJoin b").list();
assertEquals(4, books.size());

Сгенерированный SQL:

select
    bookfetchm0_.id as id1_7_,
    bookfetchm0_.isbn as isbn2_7_,
    bookfetchm0_.publicationDate as publicat3_7_,
    bookfetchm0_.title as title4_7_
from
    BookFetchModeJoin bookfetchm0_

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    authors0_.BookFetchModeJoin_id as BookFetc1_8_0_,
    authors0_.authors_id as authors_2_8_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeJoin_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    authors0_.BookFetchModeJoin_id as BookFetc1_8_0_,
    authors0_.authors_id as authors_2_8_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeJoin_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    authors0_.BookFetchModeJoin_id as BookFetc1_8_0_,
    authors0_.authors_id as authors_2_8_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeJoin_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    authors0_.BookFetchModeJoin_id as BookFetc1_8_0_,
    authors0_.authors_id as authors_2_8_0_,
    author1_.id as id1_0_1_,
    author1_.fullName as fullName2_0_1_
from
    BookFetchModeJoin_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookFetchModeJoin_id=?

HQL запрос с «join fetch»

Чтобы корневые сущности со связанными коллекциями были загружены в одном SQL запросе, используйте оператор JOIN FETCH. Результатом запроса будет декартово произведение. Вместо 4 элементов в результирующей выборке, запрос вернет 6, потому что книги «Enterprise Integration Patterns» и «NoSQL» имеют двух авторов и будут дважды встречаться в результатах запроса. Коллекции, которые не были присоединены оператором JOIN FETCH, будут загружены согласно типу и режиму загрузки.

В данном примере будет выполнено по дополнительному запросу на каждую корневую сущность из списка результатов для загрузки списка сущностей Category.

List books = getCurrentSession().createQuery("select b from BookFetchModeJoin b join fetch b.authors a").list(); 
assertEquals(6, books.size());

Сгенерированный SQL:

select
    bookfetchm0_.id as id1_7_0_,
    author2_.id as id1_0_1_,
    bookfetchm0_.isbn as isbn2_7_0_,
    bookfetchm0_.publicationDate as publicat3_7_0_,
    bookfetchm0_.title as title4_7_0_,
    author2_.fullName as fullName2_0_1_,
    authors1_.BookFetchModeJoin_id as BookFetc1_8_0__,
    authors1_.authors_id as authors_2_8_0__
from
    BookFetchModeJoin bookfetchm0_
inner join
    BookFetchModeJoin_Author authors1_
        on bookfetchm0_.id=authors1_.BookFetchModeJoin_id
inner join
    Author author2_
        on authors1_.authors_id=author2_.id

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

select
    categories0_.BookFetchModeJoin_id as BookFetc1_9_0_,
    categories0_.categories_id as categori2_9_0_,
    category1_.id as id1_16_1_,
    category1_.description as descript2_16_1_,
    category1_.name as name3_16_1_
from
    BookFetchModeJoin_Category categories0_
inner join
    Category category1_
        on categories0_.categories_id=category1_.id
where
    categories0_.BookFetchModeJoin_id=?

Hibernate Criteria запрос и FetchMode.JOIN

В Hibernate Criteria запросах связанные коллекции с режимом загрузки FetchMode.JOINбудут загружены сразу (тип загрузки EAGER) и в одном запросе с корневыми сущностями при помощи SQL оператора JOIN. Как уже рассматривалось в прошлой статье, только одна коллекций, которая загружается со стратегией JOINможет быть типа java.util.List, остальные коллекции, которые загружаются стратегией JOINдолжны быть типа java.util.Set, иначе будет выброшено исключение org.hibernate.loader.MultipleBagFetchException.

List books = getCurrentSession().createCriteria(BookFetchModeJoin.class).list();

Будет выброшено исключение:
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags

HQL и Hibernate Criteria запросы и FetchMode.SELECT с @BatchSize

@BatchSizeустанавливает количество коллекций, которые должны быть загружены в одном SQL запросе. Если результат запроса содержит 4 сущности, каждая из которых имеет по связанной коллекции, при режим загрузки SELECTбудет выполнено 5 запросов. Один запрос для загрузки всех корневых сущностей и по одному для загрузки связанной коллекции каждой из 4 корневых сущностей. @BatchSize(size = 2)указывает ORM загружать по 2 связанные коллекции в одном запросе. Таким образом, всего будет выполнено 3 запроса вместо 5. Один запрос для загрузки всех корневых сущностей и еще 2 запроса, каждый из которых загрузит по 2 связанные коллекции для 2 корневых сущностей.

List books = getCurrentSession().createQuery("select b from BookBatchSize b").list();
assertEquals(4, books.size());

Как уже отмечалось ранее, при режиме загрузки FetchMode.SELECT HQL и Hibernate Criteria запросы ведут себя одинаково. При использовании @BatchSizeповедение также будет одинаковым.

List books = getCurrentSession().createCriteria(BookBatchSize.class).list(); 
assertEquals(4, books.size());

Сгенерированный SQL:

select
    bookbatchs0_.id as id1_4_,
    bookbatchs0_.isbn as isbn2_4_,
    bookbatchs0_.publicationDate as publicat3_4_,
    bookbatchs0_.title as title4_4_
from
    BookBatchSize bookbatchs0_

select
    authors0_.BookBatchSize_id as BookBatc1_5_1_,
    authors0_.authors_id as authors_2_5_1_,
    author1_.id as id1_0_0_,
    author1_.fullName as fullName2_0_0_
from
    BookBatchSize_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookBatchSize_id in (
        ?, ?
    )

select
    authors0_.BookBatchSize_id as BookBatc1_5_1_,
    authors0_.authors_id as authors_2_5_1_,
    author1_.id as id1_0_0_,
    author1_.fullName as fullName2_0_0_
from
    BookBatchSize_Author authors0_
inner join
    Author author1_
        on authors0_.authors_id=author1_.id
where
    authors0_.BookBatchSize_id in (
        ?, ?
    )

Выводы

Существует немало нюансов, связанных со стратегиями загрузки связанных коллекций в JPA и Hibernate, многие из которых были рассмотрены в этой и предыдущейстатьях.

Не стоит использовать одну выбранную стратегию загрузки повсюду в приложении. Каждый случай надо проанализировать индивидуально и выбрать оптимальную стратегию загрузки. Как это часто бывает, в большинстве случаев стратегия загрузки по умолчанию будет оптимальным вариантом. Если приложение испытывает проблемы с производительностью, которые вызваны неправильным выбором стратегии загрузки, для анализа пригодятся следующие свойства Hibernate конфигурации: hibernate.show_sql=true, hibernate.format_sql=true и hibernate.use_sql_comments=true.


Viewing all articles
Browse latest Browse all 8115

Trending Articles