Ограничение результатов запроса с помощью JPA и Spring Data JPA
1. Вступление
В этом руководстве мы перейдем кlearn about limiting query results сJPA иSpring Data JPA.
Сначала мы взглянем на таблицу, которую хотим запросить, а также на SQL-запрос, который мы хотим воспроизвести.
Затем мы сразу рассмотрим, как этого добиться с помощью JPA и Spring Data JPA.
Давайте начнем!
2. Тестовые данные
Ниже представлена таблица, к которой мы будем обращаться в этой статье.
Вопрос, на который мы хотим ответить: «Какое первое место занято и кто его занимает?».
Имя |
Фамилия |
Номер места |
Jill |
кузнец |
50 |
Eve |
Джексон |
94 |
Fred |
Bloggs |
22 |
Рики |
Бобби |
36 |
Siya |
Колиси |
85 |
3. SQL
С помощью SQL мы могли бы написать запрос, который выглядит примерно так:
SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;
4. Настройка JPA
В JPA нам сначала нужен Entity, чтобы отобразить нашу таблицу:
@Entity
class Passenger {
@Id
@GeneratedValue
@Column(nullable = false)
private Long id;
@Basic(optional = false)
@Column(nullable = false)
private String fistName;
@Basic(optional = false)
@Column(nullable = false)
private String lastName;
@Basic(optional = false)
@Column(nullable = false)
private int seatNumber;
// constructor, getters etc.
}
Затем нам нужен метод, который инкапсулирует наш код запроса, реализованный здесь какPassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit):
@Repository
class PassengerRepositoryImpl {
@PersistenceContext
private EntityManager entityManager;
@Override
public List findOrderedBySeatNumberLimitedTo(int limit) {
return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber",
Passenger.class).setMaxResults(limit).getResultList();
}
}
В нашем методе репозитория мы используемEntityManager для созданияQuery, для которого мы вызываем методsetMaxResults().
Этот вызовQuery#setMaxResults в конечном итоге приведет к добавлению оператора limit к сгенерированному SQL:
select
passenger0_.id as id1_15_,
passenger0_.fist_name as fist_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number limit ?
5. С данными Spring JPA
Мы также можем генерировать наш SQL, используя Spring Data JPA.
5.1. first илиtop
Один из способов приблизиться к этому - использовать вывод имени метода с ключевыми словамиfirst илиtop..
При желании мы можем указать число в качестве максимального размера результата, который будет возвращен. Если мы его опускаем, Spring Data JPA принимает размер результата 1.
Вспоминая, что мы хотим знать, какое первое место занято и кто его занимает, мы можем получить его, опуская число двумя способами:
Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();
Если мы ограничимся одним результатом экземпляра, как указано выше, то мы также можем обернуть результат, используяOptional:
Optional findFirstByOrderBySeatNumberAsc();
Optional findTopByOrderBySeatNumberAsc();
5.2. Pageableс
В качестве альтернативы мы можем использовать объектPageable:
Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
Если мы посмотрим на реализацию по умолчаниюJpaRepository,,SimpleJpaRepository, we увидим, что он также вызываетQuery#setMaxResults:
protected Page < S > readPage(TypedQuery < S > query,
Class < S > domainClass, Pageable pageable,
@Nullable Specification < S > spec) {
if (pageable.isPaged()) {
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
}
return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> {
return executeCountQuery(this.getCountQuery(spec, domainClass));
});
}
5.3. сравнение
Обе эти альтернативы будут производить SQL, который мы ищем:
select
passenger0_.id as id1_15_,
passenger0_.fist_name as fist_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number asc limit ?
Сfirst andtop в пользу соглашения иPageable в пользу конфигурации.
6. Заключение
Ограничение результатов запроса вJPA немного отличается от SQL - мы не включаем ключевое слово limit непосредственно в нашиJPQL.
Вместо этого мы просто вызываем один методQuery#maxResults или включаем ключевое словоfirst илиtop в имя нашего методаSpring Data JPA.
Как всегда, вы можете найти кодover on GitHub.