@ManyToOne и @BatchSize

Я нашел в каком-то старом коде странную вещь (по крайней мере, для меня).

Поле, помеченное @ManyToOne, также помечено @BatchSize.

Я всегда думал, что аннотация @BatchSize влияет только на аннотацию на уровне класса или коллекции (@OneToMany) и влияет на предварительную выборку при итерации.

Но, возможно, я ошибаюсь и пометка @ManyToOne с помощью @BatchSize на что-то влияет. Я не могу найти ответ в документации.

Имеет ли смысл аннотировать @ManyToOne с помощью @BatchSize?


person Łukasz Rzeszotarski    schedule 24.10.2012    source источник


Ответы (3)


@ManyToOne, связанный с @BatchSize, может иметь смысл, только если соответствующее поле помечено как lazy (lazy=true).

В самом деле, если поле не lazy, оно по определению уже загружено, так как включающая сущность загружена, поэтому проблема вызовов базы данных не применяется.

Представьте себе класс Person, у которого есть коллекция из элементов ShoesPair (ShoesPair.class), и в этом классе присутствует поле owner, помеченное как ленивое (поскольку оно является необязательным и не содержит важной информации при получении конкретной пары обуви).

Требуется перебрать 25 пар обуви (25 ShoesPair объектов), чтобы найти их владельца.

Если поле owner (соответствующее одному человеку) снабжено только аннотацией @ManyToOne, будет выбрано 25 для базы данных.

Однако, если помечено @BatchSize(size=5), будет всего 5 вызовов, что повысит производительность.

Из документации по Hibernate, уточняется, что размер пакета применяется не только к коллекциям:

Вы можете также включить пакетную загрузку коллекций.

Hibenate особо упоминает @OneToMany случаев, потому что они применяются с полями, которые в 90% случаев помечены как lazy.

person Mik378    schedule 24.10.2012
comment
Если это действительно работает так, как вы написали, меня устраивает. Но в документации найти не удалось. Там вижу только это: 19.1.5. Использование пакетной выборки Используя пакетную выборку, Hibernate может загружать несколько неинициализированных прокси-серверов при доступе к одному прокси. Пакетная выборка - это оптимизация стратегии отложенной выборки. Вы можете настроить пакетную выборку двумя способами: на уровне класса и на уровне коллекции. - person Łukasz Rzeszotarski; 24.10.2012
comment
Я имею в виду фрагмент: на уровне класса и на уровне коллекции. - person Łukasz Rzeszotarski; 24.10.2012
comment
@ Ukasz Rzeszotarski Я думаю, что это довольно очевидно в документации и поэтому не упоминается. Действительно, эта концепция применима только к ленивым объектам. Я обновил свой ответ. - person Mik378; 24.10.2012
comment
Может быть, очевидно, а может и нет. Документация должна охватывать все возможности или быть написана в более общем виде - как вы написали: «концепция применима к ленивым объектам». Но спасибо за ответ. Я приму его, но, может быть, кто-то еще хочет что-то добавить. - person Łukasz Rzeszotarski; 24.10.2012
comment
Но в документации объясняется аналогичный пример с полем owner. Этот может быть помечен как @ManyToOne (не имеет значения). По-моему, в этот пример входит ваша заявка. - person Mik378; 24.10.2012
comment
Я обнаружил, что в моем случае это не так, что соответствует тому, что объясняет @chris в своем комментарии. - person DanielM; 03.10.2018
comment
Мне было непонятно ни из ответа, ни из комментариев, где разместить аннотацию. Этот ответ на аналогичный вопрос объясняет это более четко: stackoverflow.com/a/27734286/2018219 - person DanielM; 03.10.2018

Я думаю, что вопрос относится к объединению @ManyToOne и @BatchSize в одном поле, например:

@ManyToOne
@BatchSize(size = 5)
private User owner;

Этот вариант использования не поддерживается Hibernate, по крайней мере, при использовании аннотаций. Единственные способы использования пакетной выборки, упомянутые в документации:

  • В полях коллекции, т.е. @OneToMany или @ManyToMany (но не @ManyToOne)
  • На извлекаемом классе сущности

E.g.:

@Entity
@BatchSize(size = 5)
public class User {
  ...
}

Этот последний случай позволяет выполнять пакетирование для всех отношений типа User, включая отношения «многие к одному». Однако с помощью аннотации к классу сущности невозможно управлять поведением от поля к полю.

Поиск в исходном коде Hibernate для всех случаев использования @BatchSize подтверждает отсутствие поддержки для вашего использования. Из того, что я вижу в AnnotationBinder .java, аннотация @BatchSize проверяется только в классе сущности и в полях, которые имеют какую-либо аннотацию @XxxToMany.

person chris    schedule 20.12.2013
comment
Мне ваш ответ очень интересен. Кажется, что это противоречит принятой ОП. Я не проверяю ваше исследование, но вы меня убедили, поэтому я поддерживаю ваш ответ. Было бы здорово, если бы это разрешил специалист. - person Stijn de Witt; 16.11.2015

Решение проблемы запроса N + 1 с помощью Hibernate

1 Использование критериев запросов с fetchMode

Критерии критериев = session.createCriteria (Customer.class); критерии.setFetchMode («контакт», FetchMode.EAGER);

2 HOL fetch join

3 @BatchSize

Аннотацию @BatchSize можно использовать для определения количества идентичных ассоциаций для заполнения в одном запросе к базе данных. Если к сеансу подключено 100 клиентов, а отображение коллекции «контактов» аннотируется @BatchSize размера n. Это означает, что всякий раз, когда Hibernate необходимо заполнить ленивую коллекцию контактов, он проверяет сеанс и, если у него есть больше клиентов, которым необходимо заполнить их коллекции контактов, он выбирает до n коллекций.

@OneToMany(mappedBy="customer",cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    @BatchSize(size=25)
    private Set<Contact> contacts = new HashSet<Contact>();
person Sagar Misal    schedule 25.07.2017