Как разбить JPA на запрос - программирование
Подтвердить что ты не робот

Как разбить JPA на запрос

У меня есть таблица представления с такими столбцами, как ID, Name, Code и другие свойства. Мое требование состоит в том, чтобы искать записи на основе упомянутых свойств и возвращать разбитый на страницы набор.

Это псевдокод для того, что я ищу:

searchSubmission(searchFilter sf,pageIndex,noOfRecords) {
   query = 'from submisssion where code=sf.code or id=sf.id order by id start_from (pageIndex*noOfRecords) limit noOfRecords'
   return result();
}

Кажется, есть много вариантов, таких как CriteriaBuilder, NamedQuery и т.д. Какой из них наиболее эффективен в этой ситуации?

4b9b3361

Ответ 1

Для всех объектов запросов JPA (кроме собственных запросов SQL) вы должны использовать разбиение на страницы через методы setMaxResults (int) и setFirstResult (int). Например:

  return em.createNamedQuery("yourqueryname", YourEntity.class)
      .setMaxResults(noOfRecords)
      .setFirstResult(pageIndex * noOfRecords)
      .getResultList();

JPA выполнит для вас нумерацию страниц.

Именованные запросы просто предопределены и могут быть кэшированы, в то время как другие типы создаются динамически.
Таким образом, выбор заключается в использовании JPQL, как:

Query query = em.createQuery("SELECT s FROM Submission s WHERE s.code = :code or s.id = :id ORDER BY s.id", Submission.class);

Или CriteriaBuilder API для формирования аналогичного запроса:

    CriteriaBuilder qb = em.getCriteriaBuilder();
    CriteriaQuery<Submission> cq = qb.createQuery(Submission.class);

    Root<Submission> root = cq.from(Submission.class);
    cq.where( qb.or( 
        qb.equal(root.get("code"), qb.parameter(String.class, "code")),
        qb.equal(root.get("id"), qb.parameter(Integer.class, "id"))
    ));
    Query query = em.createQuery(cq);

Не забудьте установить значения параметров, например, используя query.setParameter("id", sf.id).

Ответ 2

Вы можете использовать Pageable в методе репозитория

@Repository
public interface StateRepository extends JpaRepository<State, Serializable> {

@Query("select state from State state where state.stateId.stateCode = ?1")
public State findStateByCode(String code, Pageable pageable);

}

И на уровне сервиса вы можете создать объект Pageable:

@Autowire
StateRepository stateRepository;

public State findStateServiceByCode(String code, int page, int size) {
    Pageable pageable = new PageRequest(page, size);
    Page<Order> statePage = stateRepository.findStateByCode(code, pageable);
    return statePage.getContent();
}

Ответ 3

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

Чтобы ограничить размер базового запроса ResultSet, интерфейс Query JPA предоставляет метод setMaxResults.

Навигация по следующей странице требует размещения набора результатов там, где закончилась последняя страница. Для этого интерфейс Query JPA предоставляет метод setFirstResult.

Использование нумерации страниц с запросом JPQL выглядит следующим образом:

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();

Criteria API точно такой же, так как вам нужно создать Query из CriteriaQuery:

CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = qb.createQuery(Post.class);

Root<Post> root = cq.from(Post.class);
cq.orderBy(qb.asc(root.get("createdOn")));

List<Post> posts = em
.createQuery(cq)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();