Skip to content

Instantly share code, notes, and snippets.

@molexx
Created September 10, 2021 16:36
Show Gist options
  • Save molexx/54be53bc22e7e10570ff34b9e8f29300 to your computer and use it in GitHub Desktop.
Save molexx/54be53bc22e7e10570ff34b9e8f29300 to your computer and use it in GitHub Desktop.
Kotlin functional wrapper for Spring-data repository's pagination
/**
* Extension function for Spring-Data's CrudRepository providing a convenient wrapper to handle pagination in a Kotlin-idiomatic way.
*
* Creates a Sequence using Page and Pageable to iterate calls to a paginated Spring-Data function call.
*
* Example usage:
*
* myPagingAndSortingRepository.paginate(50) { pageable ->
* // directly call any function on the repository that returns a Page
* findAll(pageable)
* }
* // Sequence<Page<T>> - the rows of data are accessible at page.content
* .flatMap { it.content }
* // now you have Sequence<T>
* .forEach { record ->
* //operate on each record
* }
*
*/
fun <T, ID, R: CrudRepository<T, ID>> R.paginate(pageSize: Int, query : R.(Pageable) -> Page<T>) : Sequence<Page<T>> {
return generateSequence ({ query(PageRequest.of(0, pageSize))}, { prevPage : Page<T> ->
logger.info { "paginater: in sequence generator, prevPage: '$prevPage'" }
if (prevPage.hasNext()) {
logger.info { "paginater: more data (totalElements: ${prevPage.totalElements}, totalPages: ${prevPage.totalPages}), getting next pageable..." }
query(prevPage.nextPageable())
} else {
logger.info { "paginater: no more data, ending sequence after ${prevPage.totalElements} items." }
null
}
})
}
@jbotuck
Copy link

jbotuck commented Sep 10, 2021

No need for the R type parameter. You can remove the parameter and replace all the other Rs with CrudRepository<T, ID>

@molexx
Copy link
Author

molexx commented Sep 10, 2021

Oh yeah. Thanks!

@molexx
Copy link
Author

molexx commented Sep 10, 2021

@jbotuck actually that doesn't work the same... R doesn't represent precisely a CrudRepository, it represents 'any class that extends CrudRepository'. So in a usage example where MyCrudRepository extends CrudRepository and adds some functions, without R the query function's receiver is just a CrudRepository and not MyCrudRepository so I cannot call the extra MyCrudRepository functions directly from the query function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment