一、Pageable的概念
Pageable实现了分页的概念,它是一个接口,提供了分页的各种参数来进行查询。通过它我们可以方便地实现数据的分页查询,例如在网页数据展现或者手机APP上翻页展示等。
public interface Pageable {
int getPageNumber();
int getPageSize();
int getOffset();
Sort getSort();
boolean hasPrevious();
Pageable next();
Pageable previousOrFirst();
Pageable first();
}
Pageable中的方法比较简单,主要用于获取分页的一些参数。其中getPageNumber()方法表示当前页码,getPageSize()表示每页显示记录数,getOffset()表示偏移量,getSort()表示根据什么属性进行排序等等。
二、使用Pageable实现简单分页查询
使用Pageable进行分页查询的方式,通常是通过数据持久化层框架的查询函数调用。以JPA为例:
@Repository
public interface UserRepository extends JpaRepository {
Page findAll(Pageable pageable);
}
在接口中定义的findAll()方法传入的参数为Pageable类型,通过调用findAll()方法即可返回一个Page对象,该对象中封装了一些分页相关的信息,例如当前页码、总页数、总记录数、每页显示的记录数等。
接下来我们可以在controller层进行调用,并处理返回值:
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public Map getUsers(@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
Page users = userRepository.findAll(pageable);
Map result = new HashMap<>();
result.put("users", users.getContent());
result.put("currentPage", users.getNumber());
result.put("totalPages", users.getTotalPages());
result.put("totalItems", users.getTotalElements());
return result;
}
}
在controller层我们实例化了一个Pageable对象,并根据前端传递的参数进行了分页查询,最后将分页查询的结果封装到Map中返回给前端,提供给前端使用。
三、分页排序
在分页的过程中,经常需要对数据进行排序,我们可以通过Pageable接口提供的getSort()方法实现分页排序。下面的例子中,我们对username属性进行升序排序:
Pageable pageable = PageRequest.of(page, size, Sort.by("username").ascending());
类似的,如果我们需要对多个属性进行排序,只需要在Sort.by()方法中添加多个Sort.Order即可。例如,以下代码将先对username字段进行升序排序,然后对age字段进行降序排序:
Pageable pageable = PageRequest.of(page, size, Sort.by("username").ascending().and(Sort.by("age").descending()));
四、自定义分页参数
除了默认提供的分页参数,例如每页显示的记录数、当前页码等,我们还可以通过实现Pageable接口来实现自定义的分页参数。例如,我们可以实现以下代码:
public class MyPageable implements Pageable {
private int pageNo;
private int pageSize;
private String orderByColumn;
private boolean isAsc;
public MyPageable(int pageNo, int pageSize, String orderByColumn, boolean isAsc) {
this.pageNo = pageNo;
this.pageSize = pageSize;
this.orderByColumn = orderByColumn;
this.isAsc = isAsc;
}
@Override
public int getPageNumber() {
return pageNo;
}
@Override
public int getPageSize() {
return pageSize;
}
@Override
public long getOffset() {
return (long) (pageNo - 1) * pageSize;
}
@Override
public Sort getSort() {
return isAsc ? Sort.by(orderByColumn).ascending() : Sort.by(orderByColumn).descending();
}
@Override
public Pageable next() {
return new MyPageable(pageNo + 1, pageSize, orderByColumn, isAsc);
}
@Override
public Pageable previousOrFirst() {
return pageNo <= 1 ? this : new MyPageable(pageNo - 1, pageSize, orderByColumn, isAsc);
}
@Override
public Pageable first() {
return new MyPageable(1, pageSize, orderByColumn, isAsc);
}
@Override
public boolean hasPrevious() {
return pageNo > 1;
}
}
自定义的MyPageable类实现了Pageable接口,并覆盖了其所有方法。其中,我们可以实现自定义的分页参数,例如orderByColumn属性表示按照哪个字段进行排序,isAsc表示是否是升序排列等。实现后,我们就可以直接使用new MyPageable()的方式来进行分页查询。
五、总结
总的来说,使用Pageable可以方便地实现数据的分页查询,减轻后端查询处理的压力,同时也可以带来更好的用户交互体验。在使用Pageable进行分页查询的过程中,我们可以通过排序、自定义参数等方式来满足不同的需求。