Spring Data 的 Page 接口进行数据分页返回了很多很多垃圾信息,
实际上我只需要下面这些分页信息:
"total_elements": 5,
"total_pages": 3,
"page_number": 2,
"number_of_elements": 2
{
"request_id": "0062f2bd-b9d8-4452-a10b-9e6e4d66d077",
"code": "0",
"message": "OK",
"description": "",
"data": {
"content": [
{
"id": 7132,
"uuid": "663307d9-cee4-438e-bbc8-eed4a364527a",
"user_id": 5,
"name": "小米激光电视",
"level": 3,
"created_at": 1524651291372
},
{
"id": 6867,
"uuid": "9e0059d8-eae4-470d-a773-67b1f6783c99",
"user_id": 4,
"name": "激光电视要用菲涅尔幕布才对",
"level": 3,
"created_at": 1524651226885
}
],
"pageable": {
"sort": {
"sorted": true,
"unsorted": false
},
"offset": 2,
"page_size": 2,
"page_number": 1,
"paged": true,
"unpaged": false
},
"total_pages": 3,
"last": false,
"total_elements": 5,
"size": 2,
"number": 1,
"number_of_elements": 2,
"first": false,
"sort": {
"sorted": true,
"unsorted": false
}
}
}
上面是 Spring Data Commons 的 Page 接口对数据库查询进行分页返回的数据.
Repository 的接口为:
Page<User> getChildrenByParentId(Pageable page, String parentId);
完整的 Repository:
@Repository
public interface UserRepository extends Neo4jRepository<User, UUID> {
@Query(
value = "MATCH (u:User)-[r:MANAGE_BY]->(p:User {uuid: {1}}) RETURN u",
countQuery = "MATCH (u:User)-[r:MANAGE_BY]->(p:User {uuid: {1}}) RETURN COUNT(*)"
)
Page<User> getChildrenByParentId(Pageable page, String parentId);
@Query(value = "MATCH (u:User) RETURN u", countQuery = "MATCH (u:User) RETURN COUNT(*)")
Page<User> getUsers(Pageable page);
Optional<User> findByUuid(UUID uuid);
}
我们看到返回了很多多余的, 重复的数据. 为了解决这个问题, 创建一个Pagination DTO(PageChunk
)来包装一下分页数据. 这个类的作用很简单就是包含每一次分页的内容和分页元数据(搜索结果总数, 当前页号, 总页数, 当前页包含多少项)
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
public class PageChunk<T> {
private List<T> content = new ArrayList<>();
private long totalElements;
private int totalPages;
private int pageNumber;
private int numberOfElements;
}
原来的控制器方法
@GetMapping(path = "/children/{id}")
public Mono<Response<Page<User>>> getChildren(
@NotBlank @PathVariable String id,
@RequestParam(required = false) Integer page
) throws ResourceNotFoundException {
Sort sort = new Sort(Sort.Direction.DESC, "u.created_at");
PageRequest request = PageRequest.of(page == null ? 0 : page, 2, sort);
return Mono.just(userRepository.getChildrenByParentId(request, id))
.map(Response::new);
}
修改后的控制器方法
@GetMapping(path = "/children/{id}")
public Mono<Response<PageChunk<User>>> getChildren(
@NotBlank @PathVariable String id,
@RequestParam(required = false) Integer page
) throws ResourceNotFoundException {
Sort sort = new Sort(Sort.Direction.DESC, "u.created_at");
PageRequest request = PageRequest.of(page == null ? 0 : page, 2, sort);
return Mono.just(userRepository.getChildrenByParentId(request, id))
.map(this::pageChunk)
.map(Response::new);
}
private PageChunk<User> pageChunk(Page<User> page) {
PageChunk<User> chunk = new PageChunk();
chunk.setContent(page.getContent());
chunk.setTotalPages(page.getTotalPages());
chunk.setTotalElements(page.getTotalElements());
chunk.setPageNumber(page.getPageable().getPageNumber() + 1);
chunk.setNumberOfElements(page.getNumberOfElements());
return chunk;
}
Web 控制器我采用了Webflux 来开发的, 因此使用了 Mono 对返回的对象进行包装, 其中还有一个自定义的Response对象, 它的作用是让我们的JSON应答有一个通用的格式.
Response 类的定义如下:
import lombok.Getter;
import lombok.Setter;
import java.util.UUID;
@Getter
@Setter
public class Response<T> {
private String requestId;
private String code = "";
private String message = "";
private String description = "";
private Object data = "";
public Response(T data, String code, String message) {
this.requestId = UUID.randomUUID().toString();
this.data = data;
this.code = code;
this.message = message;
}
/**
* 正确结果
*
* @param data
*/
public Response(T data) {
this.requestId = UUID.randomUUID().toString();
this.data = data;
this.code = "0";
this.message = "OK";
}
}
然后是修改后的JSON响应结果
{
"request_id": "8f381bfa-8ed9-442c-91fb-2678a33dee7f",
"code": "0",
"message": "OK",
"description": "",
"data": {
"content": [
{
"id": 7132,
"uuid": "663307d9-cee4-438e-bbc8-eed4a364527a",
"user_id": 5,
"name": "小米激光电视",
"level": 3,
"created_at": 1524651291372
},
{
"id": 6867,
"uuid": "9e0059d8-eae4-470d-a773-67b1f6783c99",
"user_id": 4,
"name": "激光电视要用菲涅尔幕布才对",
"level": 3,
"created_at": 1524651226885
}
],
"total_elements": 5,
"total_pages": 3,
"page_number": 2,
"number_of_elements": 2
}
}
看起来舒服多了!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。