Возврат страницы‹Объект› в Query DSL

Я использую Query DSL и хочу, чтобы мой набор результатов возвращал объект страницы. Есть ли способ сделать это в Query DSL? Если да, то как будет выглядеть мой запрос? Я использую JPAQuery, и у меня есть QClasses

Структура метода такова

public Page<Object> searchPerson(String name,String phone){
 Page<Object> results=null;
 JPQLQuery query = new JPAQuery(entityManager);
 QPerson person = QPerson.person;
   //I am assuming my query would go here 
  results = query.from(person). ?????  


return results;} 

Помощь!


person Rudy    schedule 15.03.2016    source источник
comment
@Timo Westkämper Помогите!   -  person Rudy    schedule 15.03.2016
comment
К какому типу относится объект Page? Используете ли вы Spring Data JPA (org.springframework.data.domain.Page?). Если это так, вам следует взглянуть на: spring.io/blog/2011/04/26/. Вы можете использовать метод findAll Spring Data со спецификациями и параметром Pageable или напрямую использовать CriteriaBuilder.   -  person meleagros    schedule 15.03.2016
comment
@meleagros Да, я видел эту статью, но если вы прочитаете ее, весь смысл использования Query DSL не в том, чтобы использовать CriteriaBuilder. Я просто хочу, чтобы мой запрос возвращал Page‹Object› точно так же, как JPA. В JPA вы можете сказать Page‹Object› findByname(String name,Pageable pageable); это может вернуть мне запрос, который мне нужен по имени. Я хочу сделать то же самое с QUERY DSL.... ПОМОГИТЕ!!   -  person Rudy    schedule 15.03.2016
comment
Как я уже сказал, вы можете использовать метод findAll customerRepo.findAll(person.age.eq(18), new PageRequest...);   -  person meleagros    schedule 15.03.2016


Ответы (2)


Вот моя реализация для Paging с QueryDSL. PageRequest определяет параметры для нашего запроса (лимит и страница):

public class PageRequest {
    protected Long page = 1l;// 1 is the first page
    protected Integer limit = 10;

    public PageRequest(Long page, Integer limit) {
        this.limit = limit;
        this.page = page;   
    }

    public Long getPage() {
        return page;
    }

    public Integer getLimit() {
        return limit;
    }

    public Long getOffset() {
        return (page - 1l) * limit;
    }
}

Класс Page содержит результат (здесь атрибут objects) запроса и может реализовывать методы для создания удобных ссылок на страницы.

public class Page<T> extends PageRequest {

    protected Collection<T> objects;
    private Long totalCount;
    private Long pageCount;
    private Boolean hasPageLinkPrev;
    private Boolean hasPageLinkNext;
    private Collection<Long> pageLinks;

    public Page(Long page, Integer limit, Long totalCount, Collection<T> objects) {

        this.page = page;
        this.limit = limit;
        this.totalCount = totalCount;
        this.objects = objects;

        this.pageCount = totalCount / limit;
        if (totalCount % limit > 0) {
            this.pageCount = this.pageCount + 1;
        }

        this.hasPageLinkPrev = page > 1;
        this.hasPageLinkNext = page < this.pageCount;

        this.pageLinks = new ArrayList<>();
        if (this.pageCount != 1) {
            this.pageLinks.add(1l);
            if (page > 3l) {
                this.pageLinks.add(-1l);
            }
            if (page > 2l) {
                if (page.equals(this.pageCount) && this.pageCount > 3l) {
                    this.pageLinks.add(page - 2l);
                }
                this.pageLinks.add(page - 1l);
            }
            if (page != 1l && !page.equals(this.pageCount)) {
                this.pageLinks.add(page);
            }
            if (page < this.pageCount - 1l) {
                this.pageLinks.add(page + 1l);

                if (page == 1l && this.pageCount > 3l) {
                    this.pageLinks.add(page + 2l);
                }
            }
            if (page < this.pageCount - 2l) {
                this.pageLinks.add(-1l);
            }
            this.pageLinks.add(this.pageCount);
        }
    }

    public Page(PageRequest pageRequest, Long totalCount, Collection<T> objects) {
        this(pageRequest.getPage(), pageRequest.getLimit(), totalCount, objects);
    }

    public Long getTotalCount() {
        return this.totalCount;
    }

    public Long getPageCount() {
        return this.pageCount;
    }

    public Long getPage() {
        return this.page;
    }

    public Integer getLimit() {
        return this.limit;
    }

    public Boolean getHasPageLinkPrev() {
        return this.hasPageLinkPrev;
    }

    public Boolean getHasPageLinkNext() {
        return hasPageLinkNext;
    }

    public Collection<Long> getPageLinks() {
        return pageLinks;
    }

    public Collection<T> getObjects() {
        return objects;
    }
}

С этим материалом не очень сложно создать запрос и поместить результаты в наш объект страницы. Одна из возможностей — написать общий метод в базовом классе классов репозитория:

    protected <T> Page<T> getPage(JPQLQuery<T> query, PageRequest pageRequest) {

        List<T> resultList = query
            .offset(pageRequest.getOffset())
            .limit(pageRequest.getLimit())
            .fetch();

        Long totalCount = query.fetchCount();
        return new Page<T>(pageRequest, totalCount, resultList);
    }

В своем классе репозитория вы создаете свой запрос для конкретного варианта использования. Затем вы можете использовать метод getPage для получения результатов в файле Page.

public Page<Person> searchPerson(String name,
                                 String phone,
                                 PageRequest request){
  Page<Person> results=null;
  JPQLQuery<Person> query = new JPAQuery<>(entityManager);
  QPerson person = QPerson.person;
  query = query.from(person)
     .where(person.name.eq(name)
         .and(person.phone.eq(phone)));
  return getPage(query, request);
} 
person Meiko Rachimow    schedule 15.03.2016

Решением для вышеизложенного было использование BooleanBuilder, реализованного в методе выше, и изменение имени метода для возврата объекта Person. Проверьте BooleanBuilder.

QPerson person= QPerson.person;
BooleanBuilder builder = this.getBuilder(name, phone,page, pageSize, sortFlag, sortItem);
    PageRequest pg = getPRequest(page, pageSize);
    Page<Person> pages personRepo.findAll(builder,pg);
  return pages;

а затем реализован метод getBuilder для него, который приведен ниже

public BooleanBuilder getBuilder(String name, String phone, Integer page, Integer pageSize, String sortFlag, String sortItem) {

    QPerson person = QPerson.person;
    BooleanBuilder builder = new BooleanBuilder();
    builder.and(person.name.startsWith(name));
    return builder;
}

и, наконец, реализовал метод getPRequest следующим образом.

public PageRequest getPRequest(Integer page, Integer pageSize) {
    return new PageRequest(page, pageSize);
}

Ооооочень счастливых дней!

person Rudy    schedule 16.03.2016
comment
Что, если мне нужно указать граф сущностей, чтобы избежать N+1? - person wmakley; 03.06.2020