【问题标题】:Spring JPA: find by multiple IDs with PaginationSpring JPA:使用分页查找多个 ID
【发布时间】:2021-06-22 02:22:27
【问题描述】:

如何将分页应用于以下查询:

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

  @Query("select b from Building b where b.id in :ids" )
  Page<Post> findByIds(@Param("ids") List<Long> postIdsList);
...
}

所有现有示例均基于接受Pageable 对象的标准findAll 方法:public Page findAll(Pageable pageable);

问题是:

  • 控制器方法签名应该是什么
  • 存储库方法参数应该是什么
  • 应如何以及将哪些参数传递给控制器​​方法
  • 我应该总是为每个请求拆分帖子 ID
  • Spring 是否会进行一次查询并将所有找到的帖子保存在内存中,或者每次下一页/上一页都会点击查询?如果是这样,它如何找出用于查找下一个/上一个帖子的 ID?

最初的实现如下:

@RestController
class PostsController {

    @Autowired

    private PostService postService;

    @GetMapping("/posts", params = "ids")
    public List<Post> getPaginatedPosts(@RequestParam List<Long> ids) {

        return postService.findPaginatedPosts(ids);
    }
}

@Repository
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

  @Query("select b from Building b where b.id in :ids" )
  Page<Post> findByIds(@Param("ids") List<Long> postIdsList);
...
}

我省略了 PostServiceImpl 中的代码 qui 实现了 PostService 并且只调用了 PostRepository#findByIds 方法。

【问题讨论】:

  • 这引出了一个问题:如果客户端知道它应该获取的 id,为什么不通过简单地限制请求中发送的 id 列表来处理分页?
  • @crizzis:因为前面有超过 20 个 ID,通过添加分页/排序参数来调整 URL 比玩集合并到处剪切它更容易页。所以我更愿意让 Spring 就地执行。更重要的是,我认为这就是大多数分页库的工作方式。

标签: spring-boot rest spring-data-jpa pagination


【解决方案1】:

试试这个:

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

  @Query( "select o from Building b where id in :ids" )
  Page<Post> findByIds(@Param("ids") List<Long> postIdsList,Pageable pageRequest);
...
}

在控制器中询问 pageSize 和 pageNo,如果它为空,则设置一个默认值,例如 pageNo = 0, pageSize=10。

将这些值传递给服务层服务应该创建可分页对象调用findByIds(ids, pagable); 并将页面返回给控制器。

你可以参考这个: https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-seven-pagination/

【讨论】:

  • 感谢您的链接,即使它是 2012 年的,它仍然有用:)。我还看了最新的Spring Data Rest docs。
【解决方案2】:

这是我给你的解决方案,加上上面的 cmets 建议。

  1. 定义一个可以扩展 JpaRepositoryPagingAndSortingRepository 的存储库,如下所示:
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

  @Query("select p from Post p where p.id in :ids" )
  Page<Post> findByIds(@Param("ids") List<Long> postIdsList);
...
}
  1. 创建服务类及其实现:
public interface PostService {
  List<PostDTO> getPostsList(List<Long> ids, Pageable pageable);
...
}

@Service
@Slf4j
public class PostServiceImpl implements PostService {
...
  @Autowired
  private PostRepository postRepository;

...
  @Override
  public List<PostDTO> getPostsList(List<Long> ids, Pageable pageable) {
        List<PostDTO> resultList = new ArrayList<>();
        Page<Post> paginatedPosts = postRepository.findByIds(ids, pageable);

        List<Post> posts = paginatedPosts.getContent();
        posts.forEach(post -> resultList.add(convertToPostDTO(post)));

        return resultList;
    }

最后,PostsController 部分:

@RestController
@RequestMapping("/api")
class PostsController {

  @Autowired
  private PostService postService;
...
    @GetMapping(value = "/posts", params = "ids")
    public ResponseEntity <List<PostDTO>>getPostsList(@RequestParam List<Long> ids, Pageable pageable) {
        List<PostDTO> postsList = postService.getPostsList(ids, pageable);
        return new ResponseEntity<>(postsList, HttpStatus.OK);
    }

请求应该包含pagesize URL参数(默认情况下,page0size20):

http://localhost:8080/api/posts?ids=1050,1049,1048,1043,1042,1041,1040,1039,1038&size=5&page=1&sort=id

在上面的示例中,我总共有 9 条记录,我明确设置了参数以将结果列表限制为 5 条并仅显示第二页以及按 id 对它们进行排序。

如果您不提供它们,将使用默认值(page = 0,size = 20)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-16
    • 2012-07-25
    • 2018-05-22
    • 2023-03-11
    • 2013-09-15
    • 2017-09-10
    • 1970-01-01
    • 2014-08-10
    相关资源
    最近更新 更多