Search code examples
javaspringspring-bootdesign-patternsspring-data

Sort order in search functionality


I use this code to get DB rows using JPA and Spring:

return transactionService.findAll(page, size)


        public Page<PaymentTransactions> findAll(int page, int size) {
        return dao.findAll(PageRequest.of(page,size, new Sort(Sort.Direction.DESC, "createdAt")));
        }

I would like to implement the same sorting for this code:

return transactionService.getAllBySpecification(specification, pageable)

      @Override
      public Page<PaymentTransactions> getAllBySpecification(final Specification<PaymentTransactions> specification, final Pageable pageable) {
          return dao.findAll(specification, pageable);
      }

Do you know how I can implement sorting direction by column using specification. Something like this:

return dao.findAll(specification, PageRequest.of(page,size, new Sort(Sort.Direction.DESC, "createdAt")));

Additionnal question:

Can I set Pagable object with sort direction? Something like this:

      @Override
      public Page<PaymentTransactions> getAllBySpecification(final Specification<PaymentTransactions> specification, final Pageable pageable) {
          return dao.findAll(specification, PageRequest.of(pageable, new Sort(Sort.Direction.DESC, "createdAt")));
      }

Solution

  • You don't need anything else other than JpaSpecificationExecutor. Spring will use this interface to automatically create the:

    Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable)

    method you seem to be looking for. So, it is unclear what the problem is, maybe you are importing the wrong classes? Or if you just want to generate PageRequest for the getAllBySpecification using page and size you can have something like this:

        public Page<Entity> getAllBySpecification(
                Specification<Entity> specification, 
                int page, int size) {
            
            return dao.findAll(specification, createMyPageRequest(page, size));
        }
    
        private PageRequest createMyPageRequest(int page, int size) {
            return PageRequest.of(page, size, new Sort(Sort.Direction.DESC, "createdAt"));
        }
    

    In any event, if you need a complete compiling example of these APIs...

    can you show me some code example please?

    ... here it is:

    import org.springframework.data.domain.*;
    import org.springframework.data.jpa.domain.Specification;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    
    public class SortFunctionality {
        private Dao dao;
        
        public Page<Entity> findAll(int page, int size) {
            return dao.findAll(createMyPageRequest(page, size));
        }
    
        public Page<Entity> getAllBySpecification(
                Specification<Entity> specification, 
                int page, int size) {
            
            return dao.findAll(specification, createMyPageRequest(page, size));
        }
        
        public Page<Entity> getAllBySpecification(
                Specification<Entity> specification, 
                Pageable pageable) {
            
            PageRequest pageRequest = createMyPageRequest(
                    pageable.getPageNumber(), 
                    pageable.getPageSize());
            
            return dao.findAll(specification, pageRequest);
        }   
    
        private PageRequest createMyPageRequest(int page, int size) {
            return PageRequest.of(page, size, new Sort(Sort.Direction.DESC, "createdAt"));
        }
    
        static interface Dao extends 
            JpaRepository<Entity, Integer>, JpaSpecificationExecutor<Entity> {}
        
        static class Entity {}
    }
    

    Additional Question's Edit:

    Yes you can achieve this by extracting the pageNumber and the pageSize from the Pageable argument and using them to create your custom PageRequest (PageRequest with hardcoded sorting criteria) with the createMyPageRequest utility that I included in the demo code. Finally, you can use that PageRequest to invoke the findAll method as usual:

        public Page<Entity> getAllBySpecification(
                Specification<Entity> specification, 
                Pageable pageable) {
            
            PageRequest pageRequest = createMyPageRequest(
                    pageable.getPageNumber(), 
                    pageable.getPageSize());
            
            return dao.findAll(specification, pageRequest);
        }   
    

    I updated the previous full demo to reflect this new addition as well. Also it is a little bit refactored, so if you paste this new method over a copy previous version of the demo it will have errors.

    Complete code on GitHub

    Hope this helps.