我正在寻找一种解决方案,以使用Cassandra(版本3.11.3
)数据库为基于Spring Boot的REST服务实现分页。我们将Spring Boot 2.0.5.RELEASE
与spring-boot-starter-data-cassandra
用作依赖项。
由于Spring Data的CassandraRepository<T, ID>
接口没有扩展PagingAndSortingRepository
,所以我们没有像JPA
那样获得完整的分页功能。
我阅读了Spring Data Cassandra文档,并找到了一种可能的方法来实现Cassandra和Spring Data的分页,因为CassandraRepository
接口具有以下可用的方法Slice<T> findAll(Pageable pageable);
。我知道Cassandra无法获得特定的页面即席显示,并且始终需要页面0来遍历所有页面,因为CassandraPageRequest
中记录了它:
特定于Cassandra的{@link PageRequest}实现提供对{@link PagingState}的访问。该类允许创建第一个页面请求,并通过Cassandra分页表示,它基于获取的页面的进度,并允许仅向前导航。 访问特定页面需要提取所有页面,直到到达所需页面为止。
在我的用例中,我们有> 1.000.000数据库条目,并希望在我们的单页应用程序中分页显示它们。
我当前的方法如下所示:
@RestController
@RequestMapping("/users")
public class UsersResource {
@Autowired
UserRepository userRepository;
@GetMapping
public ResponseEntity<List<User>> getAllTests(
@RequestParam(defaultValue = "0", name = "page") @Positive int requiredPage,
@RequestParam(defaultValue = "500", name = "size") int size) {
Slice<User> resultList = userRepository.findAll(CassandraPageRequest.first(size));
int currentPage = 0;
while (resultList.hasNext() && currentPage <= requiredPage) {
System.out.println("Current Page Number: " + currentPage);
resultList = userRepository.findAll(resultList.nextPageable());
currentPage++;
}
return ResponseEntity.ok(resultList.getContent());
}
}
BUT使用这种方法,我必须在将所有数据库条目提取到内存并进行迭代直到找到正确的页面之前找到请求的页面。是否有其他方法可以找到正确的页面,还是必须使用当前的解决方案?
我的Cassandra表定义如下:
CREATE TABLE user (
id int, firstname varchar,
lastname varchar,
code varchar,
PRIMARY KEY(id)
);
我所做的是创建一个具有内容和pageingState哈希值的页面对象。
在初始页面中,我们有简单的页面调度
Pageable pageRequest = CassandraPageRequest.of(0,5);
一旦执行查找,我们就得到切片
Slice<Group> slice = groupRepository.findAll(pageRequest);
使用切片可以获取分页状态
page.setPageHash(getPageHash((CassandraPageRequest) slice.getPageable()));
where
private String getPageHash(CassandraPageRequest pageRequest) {
return Base64.toBase64String(pageRequest.getPagingState().toBytes());
}
最终返回具有List内容和pageingState作为pageHash的Page对象