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

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

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

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

【问题讨论】:

    标签: spring mongodb spring-data spring-boot spring-data-mongodb


    【解决方案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);
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-10-29
            • 2013-07-28
            • 2020-11-23
            • 1970-01-01
            • 2021-07-25
            • 1970-01-01
            • 2019-03-13
            • 1970-01-01
            相关资源
            最近更新 更多