Search code examples
javaspring-bootkotlinspring-data-jpaspring-data

Limit resuts returned by Spring Scroll Api


I want to implement the scroll API from Spring. So that when a user scrolls in the Front End, new data is loaded on every request from the Front end.

I try to limit the results returned by Spring and I am trying various ways.

  1. PageRequest
    // Service
    fun getOrders(customerId: Long): List<OrderDto> {
        val customer = customerRepository.findById(customerId).getOrElse { return emptyList() }
        val orders: WindowIterator<Order> = WindowIterator.of<Order> { position ->
            orderRepsitory.findAllByCustomerOrderByCreated(
                 customer, 
                 position as KeysetScrollPosition?,
                 PageRequest.of(0, 20)
            )
        }
            .startingAt(ScrollPosition.keyset())
        val ordersResult: MutableList<Orders> = ArrayList<Orders>()
        orders.forEachRemaining { ordersResult.add(it) }
        return ordersResult.map {
            OrderDto(...)
        }
    }


    // Order Respository
    interface OrderRepository : JpaRepository<Order, Long> {
    fun findAllByCustomerOrderByCreated(
        customer: Customer, 
        position: KeysetScrollPosition?,
        pageable: Pageable,
        ): Window<Order>
    }

This always returns the whole table.

  1. Adjust the JPA Query
    // Order Respository
    interface OrderRepository : JpaRepository<Order, Long> {
    fun findFirst5ByCustomerOrderByCreated(
        customer: Customer, 
        position: KeysetScrollPosition?,
        ): Window<Order>
    }


    // call to repository in service
    orderRepsitory.findFirst5ByCustomerOrderByCreated(
        customer, 
        position as KeysetScrollPosition?
    )

Same result, it returns the whole table.

  1. Using Limit
    // Order Respository
    interface OrderRepository : JpaRepository<Order, Long> {
    fun findAllByCustomerOrderByCreated(
        customer: Customer, 
        limit: Limit,
        ): Window<Order>
    }

    // call to repository in service
    orderRepsitory.findAllByCustomerOrderByCreated(
        customer, 
        position as KeysetScrollPosition?,
         Limit.of(20)
    )

Same result, it returns the whole table.

How to limit the results with Spring Scroll API?


Solution

  • The "problem" is your use of the WindowIterator. This will keep iterating over successive Windows (which is the point of an iterator) until there is nothing more to retrieve.

    So the problem isn't Spring Data, but rather your use of the WindowIterator. Just remove it and return the Window as is, or just use toList to convert it to a List.

    fun getOrders(customerId: Long): List<OrderDto> {
        val customer = customerRepository.findById(customerId).getOrElse { return emptyList() }
        val orders = orderRepsitory.findAllByCustomerOrderByCreated(
                 customer, 
                 position as KeysetScrollPosition?,
                 PageRequest.of(0, 20)
        return orders.toList()
        }
    }