Для этого нет решения JPA Criteria. Вы можете использовать настраиваемую функцию SQL, которая запускается во время генерации SQL-запроса. Все провайдеры JPA так или иначе поддерживают что-то подобное.
Если вы не хотите реализовывать это самостоятельно или даже хотите иметь подходящий API для построения таких запросов, я могу только порекомендовать вам реализованную мной библиотеку под названием Blaze-Persistence.
Вот документация, демонстрирующая вариант использования ограничения / смещения с подзапросами: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination.
Ваш запрос может выглядеть так с API построителя запросов:
criteriaBuilderFactory.create(entityManager, SomeEntity.class)
.where("id").in()
.select("subEntity.id")
.from(SomeEntity.class, "subEntity")
.where("subEntity.state").eq(someValue)
.orderByAsc("subEntity.id")
.setMaxResults(100)
.end()
По сути, это сводится к использованию LIMIT
функции SQL, зарегистрированной Blaze-Persistence. Поэтому, когда вы загружаете Blaze-Persistence с помощью EntityManagerFactory, вы даже можете использовать его вот так
entityManager.createQuery(
"select * from SomeEntity where id IN(LIMIT((" +
" select id " +
" from SomeEntity subEntity " +
" where subEntity.state = :someParam " +
" order by subEntity.id asc" +
"),1)) "
)
или что-то вроде
criteriaQuery.where(
cb.in(yourClass.get(YourClass_.parentId)).value(cb.function("LIMIT", subquery));
Если вы используете EclipseLink, соглашение о вызове таких функций выглядит как OPERATOR('LIMIT', ...)
.
person
Christian Beikov
schedule
03.08.2018