Можно ли ограничить размер коллекции @OneToMany с помощью Hibernate или JPA Annotations?

Если у меня есть следующая сопоставленная коллекция в POJO с использованием JPA/Hibernate Annotations:

@OneToMany(mappedBy = "columnName", fetch = FetchType.LAZY)
@OrderBy("aField")
@MapKeyJoinColumn(name = "id_fk")
@LazyCollection(value = LazyCollectionOption.EXTRA)
private Set<PojoClass> collection = new HashSet<>();

Можно ли ограничить размер загруженной коллекции конкретным номером n или установить размер страницы на ленивую загрузку первых n элементов коллекции без загрузки всех элементов или любых других элементов из других экземпляров класса (например, с @BatchSize)?

Обратите внимание, что вопрос явно ссылается на сопоставления POJO, не делая дополнительных запросов, используя критерии или любой другой способ программного ограничения размера в явных запросах.

Возможные решения, которые я рассматривал, - это найти реализацию инструкции SQL TOP в Hibernate, надеюсь, в качестве аннотации или создать пользовательский CollectionPersister для изменения сгенерированного запроса (хотя для этого потребовалось бы, чтобы оператор TOP был реализован в поддерживаемой диалекты).

Ответ 1

Это невозможно. Hibernate имеет два варианта для вас:

  • вы загружаете дочернюю коллекцию при извлечении родительского объекта
  • вы загружаете детскую коллекцию лениво при первом доступе

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

Пока вы можете использовать @Where или @Filter, эти аннотации более полезны для фильтрации содержимого коллекции, а не для ограничения ее размера.

Итак, вы всегда должны помнить, что Сборы Hibernate - это функция, а не обязательное требование. Запросы более гибкие и менее ограничивающие.

Итак, на этот раз вы должны использовать запросы:

  • HQL/JPQL
  • Критерии
  • Собственный SQL

Ответ 2

Вы можете ограничить количество записей, используя "пользовательское" имя таблицы соединений, например:

@JoinTable(name = "(select * from the_table order by some_column limit 10)")