带有可分页的 Spring 自定义查询

Posted

技术标签:

【中文标题】带有可分页的 Spring 自定义查询【英文标题】:Spring Custom Query with pageable 【发布时间】:2015-02-02 11:32:06 【问题描述】:

我想在 Spring 应用程序中实现分页。我知道使用存储库我们可以实现分页,但我们不能编写自己的数据检索查询存储库中的方法有限,也没有接受查询类的方法。

如果我们想编写自定义查询来从 mongodb 检索数据,我们必须使用 mongotemaplete,因为我知道使用 mongotemplate 我们无法实现分页。

有没有其他方法可以实现分页以及数据库查询。 任何人都可以帮助我。

【问题讨论】:

【参考方案1】:

您可以使用 Spring 的 @Query annotation 定义查询,然后将 Pageable 定义为最后一个参数:

public interface FooRepository extends MongoRepository<Foo,String>     
    @Query(value="'name': ?0")
    Page<Foo> findByMethod(String name, Pageable pageable);

然后,像这样使用它:

Page<Foo> fooPage = fooRepository.findByMethod("John", new PageRequest(0,20));

【讨论】:

Query注解末尾多了一个分号,可以去掉吗?谢谢;-) 删除了多余的分号。 您也可以将可分页参数作为第一个参数。您不需要将 ?0 更改为 ?1,因为 Pageable 不被视为 @Query 的真实参数。【参考方案2】:

这是一个没有将所有数据加载到内存中的示例。

@Autowired
private MongoTemplate mongoTemplate; 

    @Override
public Page<YourClass> findAll(/* params, ... */ @NotNull Pageable pageable) 
    Query query = query(
            where("...")
            // ... your query ...
    ).with(pageable);
    Long totalCount = mongoTemplate.count(query, YourClass.class);
    List<YourClass> results = mongoTemplate.find(query.with(pageable), YourClass.class);
    Page<YourClass> resultsWithPage = PageableExecutionUtils.getPage(results, pageable, () -> totalCount);
    return resultsWithPage;

【讨论】:

【参考方案3】:
Pageable pageableBase = PageRequest.of(0, request.getSize());
List <User> users = userRepository.findAllSignUpComplete(true, pageableBase);

公共接口 UserRepository 扩展 PagingAndSortingRepository ...

【讨论】:

【参考方案4】:

我提供了一个代码 sn-p,说明我们如何使用带有 jpa 的 springboot 实现分页,只需使用 PagingAndSortingRepository,其中包含用于分页的 inbuild 方法。

public interface PersonRepository extends PagingAndSortingRepository<Person, Integer> 



  @Service
  public class PersonServiceImpl implements PersonService
  
  @Autowired
  private PersonRepository personRepository;

  public Page<Person> listAll(int pageNumber)
   if(pageNumber>0)
  Pageable pageWithTenElements = PageRequest.of(pageNumber-1,10);
  //first param decide page and second param decide no of record

   return personRepository.findAll(pageWithTenElements);
   else 
   return null;
  

  

  @RestController
  public class AppController 
  
  @Autowired
  private PersonService personService;

   @GetMapping("/page/pageNumber")
   public ResponseEntity<List<Person>> getPersons(@PathVariable("pageNumber") pageNumber)
   List<Person> persons = personService.listAll(pageNumber).getContent();
   ResponseEntity<SkillsTierResponse> response = 
                           new ResponseEntity<List<Person>>(persons,HttpStatus.OK);
        
        return response;
   

  

【讨论】:

【参考方案5】:

如您所见,MongoTemplate 不支持完整的页面抽象。就像 KneeLess 说的,你可以使用@Query-Annotation 来做一些自定义查询。

如果这对您来说还不够,可以将 Spring Repository PageableExecutionUtils 与您的 MongoTemplate 结合使用。

例如这样:

@Override
public Page<XXX> findSophisticatedXXX(/* params, ... */ @NotNull Pageable pageable) 

    Query query = query(
            where("...")
            // ... sophisticated query ...
    ).with(pageable);

    List<XXX> list = mongoOperations.find(query, XXX.class);
    return PageableExecutionUtils.getPage(list, pageable,
              () -> mongoOperations.count((Query.of(query).limit(-1).skip(-1), XXX.class));

Spring 存储库也在做同样的事情。如您所见here,它们也触发了两个查询。

【讨论】:

那个杀手参考!我一直在寻找几个小时! xD 太棒了!我花了几个小时,因为我没有Query.of(query).limit(-1).skip(-1),而只是一个直的query 这会加载内存中的所有记录,然后再分页吗?【参考方案6】:

只是把它拿出来以防有人需要它。

SpringData 有自定义查询的方法:

final Pageable pageableRequest = new PageRequest(0, 2);
Query query = new Query();
query.with(pageableRequest);

【讨论】:

不能从存储库中使用它,它说它是受保护的访问 @viniciusgati,我认为这是因为 API 在以后的版本中发生了变化。新的等价物是PageRequest.of(0, 2)【参考方案7】:

通过扩展 Spring Data PagingAndSortingRepository 接口,您可以获得一些常用的方法,如保存、查找、findAll 和删除,还可以添加自己的自定义查询:

public interface Repository extends PagingAndSortingRepository<Book, ID extends Serializable> 

    // Common method
    Page<Book> findAll(Pageable pageable);

    // Custom query based on Spring Data naming convention
    Page<Book> findByNameOrDescription(String name, String description, Pageable pageable);


【讨论】:

以上是关于带有可分页的 Spring 自定义查询的主要内容,如果未能解决你的问题,请参考以下文章

引导表服务器端分页的自定义参数

SpringBoot 2.2.2:用于自定义分页的 Jackson 序列化程序不起作用

bladex中自定义分页的写法~

Mybatis源码分析自定义缓存分页的实现

laravel自定义分页的实现案例offset()和limit()

如何在带有自定义过滤器的 Spring Data mongodb 中使用分页和排序?