Spring中List到Page的转换

Posted

技术标签:

【中文标题】Spring中List到Page的转换【英文标题】:Conversion of List to Page in Spring 【发布时间】:2016-10-11 11:59:19 【问题描述】:

我正在尝试在春季将列表转换为页面。我已经使用

对其进行了转换

new PageImpl(users, pageable, users.size());

但现在我遇到了排序和分页本身的问题。当我尝试传递大小和页面时,分页不起作用。

这是我正在使用的代码。

我的控制器

    public ResponseEntity<User> getUsersByProgramId(
        @RequestParam(name = "programId", required = true) Integer programId Pageable pageable) 

    List<User> users = userService.findAllByProgramId(programId);
    Page<User> pages = new PageImpl<User>(users, pageable, users.size());

    return new ResponseEntity<>(pages, HttpStatus.OK);

这是我的用户回购

public interface UserRepo extends JpaRepository<User, Integer>

public List<User> findAllByProgramId(Integer programId);

这是我的服务

    public List<User> findAllByProgramId(Integer programId);

【问题讨论】:

好像你用错了。您检索表格的所有元素,然后将它们包装到PageImpl 中。但是您应该将PageRequest 传递给您的服务内的存储库以使其工作。你也可以发布你的服务方法和存储库的代码吗? 是的,我肯定会发布它们,但它们对于 Impl 方法来说是相当长的。但我会发布存储库一个 【参考方案1】:

这是分页列表的正确答案

public ResponseEntity<User> getUsersByProgramId(
            @RequestParam(name = "programId", required = true) Integer programId, Pageable pageable) 
        List<User> users = userService.findAllByProgramId(programId);

        final int toIndex = Math.min((pageable.getPageNumber() + 1) * pageable.getPageSize(),
                    bidList.size());
        final int fromIndex = Math.max(toIndex - pageable.getPageSize(), 0);
        Page<User> pages = new PageImpl<User>(users.subList(fromIndex, toIndex), pageable, users.size());
    
        return new ResponseEntity<>(pages, HttpStatus.OK);

【讨论】:

【参考方案2】:

我遇到了同样的问题。我使用了子列表:

final int start = (int)pageable.getOffset();
final int end = Math.min((start + pageable.getPageSize()), users.size());
final Page<User> page = new PageImpl<>(users.subList(start, end), pageable, users.size());

【讨论】:

它在我的情况下不起作用!你的 list.size() 是指 users.size() 吗? @OliverGierke 我同意您可以直接从存储库中检索Page,但情况并非总是如此,例如,如果您的实体有一个 OneToMany 关联可以为您提供List,并且您想将其公开为Page 对我来说太棒了,你让我头疼了好几天。 没试过,但即使有效,但效率不高。它正在从数据库中检索所有用户并返回一个子列表。理想的情况是从数据库中仅检索将从请求中提供服务的分页用户。 org.springframework.data.domain.Pageable.getOffset() 返回一个 long,所以我认为您需要将 pageable.getOffset() 转换为 long 或更改 start 的类型【参考方案3】:

在JHipster框架中有一个接口PageUtil

static <T> Page<T> createPageFromList(List<T> list, Pageable pageable) 
    if (list == null) 
        throw new IllegalArgumentException("To create a Page, the list mustn't be null!");
    

    int startOfPage = pageable.getPageNumber() * pageable.getPageSize();
    if (startOfPage > list.size()) 
        return new PageImpl<>(new ArrayList<>(), pageable, 0);
    

    int endOfPage = Math.min(startOfPage + pageable.getPageSize(), list.size());
    return new PageImpl<>(list.subList(startOfPage, endOfPage), pageable, list.size());

【讨论】:

【参考方案4】:

基于@shilaimuslm 评论实现。在这种情况下,如果 start > end 在 subList 中,则不会抛出异常。

List<User> users = // ...

Pageable paging = PageRequest.of(pagePagination, sizePagination);
int start = Math.min((int)paging.getOffset(), users.size());
int end = Math.min((start + paging.getPageSize()), users.size());

Page<User> page = new PageImpl<>(users.subList(start, end), paging, users.size());

【讨论】:

非常感谢,很好的例子!【参考方案5】:

根据您的要求,不要返回完整的数组列表,而是取 subblist。 您将从请求正文中的“可分页”对象中获得“偏移”和大小。

new PageImpl<User>(users.subList(start, end), pageable, users.size());

【讨论】:

【参考方案6】:

你应该按照 dubonzi 的 answer 的建议去做。

如果您仍想对给定的List 使用分页,请使用PagedListHolder:

List<String> list = // ...

// Creation
PagedListHolder page = new PagedListHolder(list);
page.setPageSize(10); // number of items per page
page.setPage(0);      // set to first page

// Retrieval
page.getPageCount(); // number of pages 
page.getPageList();  // a List which represents the current page

如果您需要排序,请使用另一个 PagedListHolder constructor 和 MutableSortDefinition。

【讨论】:

你能解释一下在这种情况下如何使用PagedListHolderMutableSortDefinition吗?【参考方案7】:

这可能是解决方案。排序和分页也可以这样工作:

控制器:

public ResponseEntity<User> getUsersByProgramId(
   @RequestParam(name = "programId", required = true) Integer programId Pageable pageable) 
       Page<User> usersPage = userService.findAllByProgramId(programId, pageable);
       Page<User> pages = new PageImpl<User>(usersPage.getContent(), pageable, usersPage.getTotalElements());

       return new ResponseEntity<>(pages, HttpStatus.OK);

服务:

Page<User> findAllByProgramId(Integer programId, Pageable pageable);

存储库:

public interface UserRepo extends JpaRepository<User, Integer>
       public Page<User> findAllByProgramId(Integer programId, Pageable pageable);

这样,我们也可以返回不同的实体页面。

【讨论】:

【参考方案8】:

为此有一个Page implementation:

Page<Something> page = new PageImpl<>(yourList);

【讨论】:

请注意,这个解决方案根本没有使用 Pageable 对象 @chomp 你能进一步解释原因吗? @TharinduEranga 因为,例如,如果您收到一个 Pageable 对象,显示 pageSize = 20 或 pageNumber = 10,它会忽略它并返回所有结果 如果您更喜欢自己构建 PageImpl 恕我直言,@shilaimuslm 的答案要准确得多 我只需要模拟一个 Page 对象进行测试。所以这是正确的。【参考方案9】:
Try This:

public Page<Patient> searchPatientPage(SearchPatientDto patient, int page, int size)
        List<Patient> patientsList = new ArrayList<Patient>();
        Set<Patient> list=searchPatient(patient);
        patientsList.addAll(list);
        int start =  new PageRequest(page, size).getOffset();
        int end = (start + new PageRequest(page, size).getPageSize()) > patientsList.size() ? patientsList.size() : (start + new PageRequest(page, size).getPageSize());

        return new PageImpl<Patient>(patientsList.subList(start, end), new PageRequest(page, size), patientsList.size());
    

【讨论】:

很棒的代码,但我想最好检查 start 和 end 如下 if(start (patientsList.subList(start, end), new PageRequest(页,大小),患者列表.size());因为如果开始比结束大,它就不会真正【参考方案10】:
//1) For a boot application create a paging repository interface
public interface PersonRepository extends PagingAndSortingRepository<Person, 
String> 
// Common CURD method are automatically implemented

//2) create a service Interface
public interface PersonService 
    Page<Person> listAllByPage(Pageable pageable); // Use common CURD findAll() method
    Page<Object> listSpecByPage(Pageable pageable, String x);


//3) create a service Impl Class of service interface
@Service
public class PersonServiceImpl implements PersonService 

    final PersonRepository personRepository;

    @Autowired
    PersonServiceImpl(PersonRepository personRepository)
    this.personRepository = personRepository;
    

    @Override
    public Page<Person> listAllByPage(Pageable pageable) 
          return personRepository.findAll(pageable);
    
    @Override
    public Page<Object> listSpecByPage(Pageable pageable, String path) 
        List<Object> objectlist = new ArrayList<Object>();
        // Do your process to get output in a list by using node.js run on a *js file defined in 'path' varriable
        Page<Object> pages1 = new PageImpl<Object>(objectlist, pageable, objectlist.size());
        return pages1;
    


//4) write your controller
public class PersonController 

    final PersonService personService;

    @Autowired
    PersonController( PersonService personService )
        this.personService = personService;
    

    @GetMapping("/get") // Use of findALL() function
    Page<Person> listed( Pageable pageable)
        Page<Person> persons = personService.listAllByPage(pageable);
        return persons;
     
    @GetMapping("/spec") // Use of defined function
    Page<Object> listSpec( Pageable pageable, String path)
        Page<Object> obj = personService.listSpecByPage(pageable, path);
        return obj;
    


【讨论】:

【参考方案11】:

您是否尝试将存储库扩展到PagingAndSortingRepository

public interface UserRepo extends PagingAndSortingRepository<Ticket, Integer> 
    Page<User> findAllByProgramId(Integer programId, Pageable pageable);

服务

Page<User> findAllByProgramId(Integer programId, Pageable pageable);

我假设您正在使用服务接口:

【讨论】:

【参考方案12】:

感谢下面的代码在我的情况下工作

    int start = pageble.getOffset();
    int end = (start + pageble.getPageSize()) > vehicleModelsList.size() ? vehicleModelsList.size() : (start + pageble.getPageSize());

【讨论】:

欢迎来到 ***!这个答案与this answer 有什么不同?如果完全一样,请重新考虑您的答案(是否应该仍然在这里)并投票给已经给出的答案。【参考方案13】:

如reference documentation 中所述,Spring Data 存储库通过简单地声明Pageable 类型的参数来支持查询方法的分页,以确保它们只读取请求的Page 所需的数据。

Page<User> page = findAllByProgramId(Integer programId, Pageable pageable);

这将返回一个Page 对象,其页面大小/设置在您的Pageable 对象中定义。无需获取列表然后尝试从中创建页面。

【讨论】:

解决了 OP 的问题,但不是问题。假设我们有一个需要转换的数据库对象(例如 User,但我们想将包含该数据的某些子集的 UserDetails DTO 的页面发送到前端)。在这种情况下,可能需要手动创建页面。 OP 没有提到任何与 DTO 或转换数据相关的内容,所以我看不出它是如何回答问题的。

以上是关于Spring中List到Page的转换的主要内容,如果未能解决你的问题,请参考以下文章

spring data jpa中的page对象带到jsp页面遍历问题

Spring Boot 中使用一个注解轻松将 List 转换为 Excel 下载

spring boot welcome-file-list

如何在 spring-data-rest 中将 Page<ObjectEntity> 映射到 Page<ObjectDTO>

Spring中利用jackson进行JSON转换

Spring Data PageImpl 没有返回正确大小的页面?