带有可分页的 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 序列化程序不起作用