在使用QueryDSL编写动态查询时,如何使用Spring的分页(使用Pageable)?

我试图使用QueryDSL分页 – 使用com.mysema.querydsl包.

我的所有Querydsl查询类型都是这样的 –

@Generated("com.mysema.query.codegen.EntitySerializer")
public class QCountry extends EntityPathBase<Country> {...}

目前,我的存储库实现类看起来像这样 –

     @Override
            public Page<Country> findPaginatedCountries(String country, Optional<String> status, Pageable pageable) {

                QCountry qCountry= QCountry.someObject;
                QActiveCountry qActiveCountry = QActiveCountry.activeCountry;

               JPAQuery jpaQuery = new JPAQuery(entityManager);

                QueryBase queryBase = jpaQuery.from(qCountry).innerJoin(qActiveCountry).fetch()
                        .where(qCountry.codeLeft.country.upper().eq(country.toUpperCase()))
                        .where(qCountry.codeRight.country.upper().eq(country.toUpperCase()));



                if(status.isPresent()){
                    queryBase = queryBase.where(qActiveCountry.id(qCountry.active.id))
                            .where(qActiveCountry.status.upper().eq(status.get().toUpperCase()));
                }
.......}

现在,我希望此动态查询返回分页响应.我想使用Spring的分页来做到这一点,而不是手动设置偏移量,大小等.

我知道我可以使用QueryDslRepositorySupport类 – 这里实现了 – https://github.com/keke77/spring-data-jpa-sample/blob/master/spring-data-jpa/src/main/java/com/gmind7/bakery/employee/EmployeeRepositoryImpl.java

以上链接的示例代码 –

@Override
    public Page<Employees> QFindByOfficeCode(long officeCode, Pageable pageable) {
        //JPAQuery query = new JPAQuery(em);
        JPQLQuery query = from(QEmployees.employees).where(QEmployees.employees.officeCode.eq(officeCode));
        query = super.getQuerydsl().applyPagination(pageable, query);
        SearchResults<Employees> entitys = query.listResults(QEmployees.employees);
        return new PageImpl<Employees>(entitys.getResults(), pageable, entitys.getTotal());
    }      

但是,要做到这一点 –

>我需要将JPQLQuery对象传递给applyPagination方法.如何在不更改代码的情况下执行此操作(Ofcourse,存储库类将扩展QueryDslRepositorySupport类).目前,我正在使用JPAQuery.

要么

>我可能需要通过扩展EntityPath而不是EntityPathBase来更改我的QueryDSL类型,以便我可以使用JPQLQuery.from()生成查询,然后使用applyPagination方法,该方法需要JPQLQuery对象.但是,我的Q类正在扩展EntityPathBase类.我应该使用com.querydsl包而不是com.mysemsa.querydsl包来生成查询类型吗?

要么

>其他选项是使用以下 – http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/querydsl/QueryDslPredicateExecutor.html#findAll-com.querydsl.core.types.Predicate-org.springframework.data.domain.Pageable-

以下代码片段 –

 Page<T> page = QueryDslPredicateExecutor.findAll(org.springframework.data.querydsl.Predicate predicate, Pageable pageable)

但是,我在两个表之间进行连接,然后使用where子句过滤结果(正如您在我的代码中看到的那样).如何在上面的findAll方法中传递谓词对象?不确定如何在其中包含联接.

如果问题不明确,请告诉我,我可以添加更多详细信息.

编辑:Country和ActiveCountry之间存在多对一的关系.
Country类具有ActiveCountry引用.我们必须在两个ID之间进行连接.有可能Country可以有null ActiveCountry.因此,我们需要内部联接 – 仅对活动国家/地区的非空值

@ManyToOne
@JoinColumn(name="id")
ActiveCountry active;

最佳答案

Step 1: Annotate the entity class with @QueryEntity

@Entity
@QueryEntity
public class Country {}

这个似乎已经解决,因为问题显示Q类.

Step 2: Have the repository interface extend QueryDslPredicateExecutor

public interface CountryRepository
                 extends PagingAndSortingRepository<Country, Long>
                         , QueryDslPredicateExecutor<Country> {
}

Step 3: Invoke the Page<T> findAll(Predicate query, Pageable page) method provided by QueryDslPredicateExecutor

public Page<Country> getCountries(String country, Optional<String> status, Pageable page) {
  QCountry root = QCountry.country;

  BooleanExpression query = root.codeLeft.country.equalsIgnoreCase(country);
  query = query.and(root.codeRight.country.equalsIgnoreCase(country));

  if (status.isPresent()) {
    query = query.and(root.active.status.equalsIgnoreCase(status));
  }

  return countryRepository.findAll(query, page);
}
点赞