425

I am using spring data and my DAO looks like

public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
    public findAllOrderByIdAsc();   // I want to use some thing like this
}

In above code, commented line shows my intent. Can spring Data provides inbuilt functionality to use such a method to find all records order by some column with ASC/DESC?

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Prashant Shilimkar
  • 8,402
  • 13
  • 54
  • 89

9 Answers9

953
public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
    public List<StudentEntity> findAllByOrderByIdAsc();
}

The code above should work. I'm using something similar:

public List<Pilot> findTop10ByOrderByLevelDesc();

It returns 10 rows with the highest level.

IMPORTANT: Since I've been told that it's easy to miss the key point of this answer, here's a little clarification:

findAllByOrderByIdAsc(); // don't miss "by"
       ^
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Sikor
  • 11,628
  • 5
  • 28
  • 43
  • 7
    For your method signature to work as intended with Spring Data JPA, you should include the "all" keyword, like so: `List findAllByOrderByIdAsc();`. Adding a return type and removing the redundant public modifier is also a good idea ;) – Håvard Geithus Apr 20 '15 at 17:11
  • 2
    I agree that public is redundant but it keeps things clear in case someone else has to work on your code. You never know who will it be :P I didnt change anything else than method name in the authors code because it's not where the problem was and if someone doesn't know what should be there, hopefully they will learn something new. Besides, it's in my example below so they wouldn't have to search god knows where, but if you insist, then so be it :) Added 'all' keyword. Thanks. – Sikor Apr 21 '15 at 08:13
  • Maybe you could mention in the answer, what Stefan Haberl wrote, I had to read his comment first before I realized whats exactly the essence of your answer. – Semaphor Nov 25 '15 at 15:12
  • @Semaphor I didn't think it will be necessary as there's only one line of code, but seeing that so many people had problems finding the little 'by', I edited my answer. Cheers. – Sikor Nov 26 '15 at 01:56
  • 13
    Still don't understand why it's necessary to add an extra `By` in the front of `OrderBy`. The [documentation doesn't tell about it](http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation). – Aritz Feb 02 '16 at 07:58
  • 7
    @XtremeBiker From the documentation link you provided: "However, the first By acts as delimiter to indicate the start of the actual criteria." Moreover, if you scroll down to section "3.4.5. Limiting query results", there is actually an example like this, but it is not explained. – Sikor Feb 02 '16 at 16:39
  • To select the max ID from a table I used: findFirstByOrderByIdDesc() – ozOli Sep 12 '16 at 10:11
  • Can I get pagination this way? for example not top 10 but the top 10~20 – Yu Jiaao Apr 25 '18 at 23:37
  • @YuJiaao Yes. You have at least 3 ways to achieve this: Option 1: `findTop10ByOrderByLevelDesc(Pageable pageRequest);` and then you pass `PageRequest.of(0, 10)` as parameter. Note that the first number is page number (0 is first page) and the second number is page size, but modifying it will not result in any changes because there is `Top10` in method name, so it will always return 10 results. Option 2: `findAllByOrderByLevelDesc(Pageable pageRequest);` Same as option 1 but page size will now be taken into account. Option 3: `findAll(Pageable pageRequest);` with Sort object inside pageRequest. – Sikor Apr 27 '18 at 21:15
  • What if we want to order by two or more columns? – Eduardo May 07 '20 at 20:42
  • 2
    @Eduardo If you want to order by two or more columns, just state another column after asc/desc keyword like this: `findAllByOrderByFirstcolAscSecondcolDesc` (not tested, but should work). However, if method name becomes too long, I suggest switching to `findAll(Pageable pageRequest)` and pass the `Sort` object inside `Pageable`, which is way more flexible, because you don't have to create a separate method for each use. This way client decides how to sort, how many rows are needed etc. – Sikor May 11 '20 at 00:08
  • Also, in this case, the "all" seems to be not needed. I had a similar situation and `findByOrderByNameAsc` worked as well as `findAllByOrderByNameAsc` – matt forsythe Dec 09 '20 at 05:35
  • 2
    @mattforsythe That's correct and this is normal spring data behaviour. If you don't put any spring data keyword after `find` (like `Top10`) it is going to return all results. I've put `All` in there because it reads better. If I remember correctly (can't test it right now) you could put anything there, like `findOhMyGodBy` and it would still behave like `findBy` or `findAllBy`. – Sikor Dec 11 '20 at 15:55
71

AFAIK, I don't think this is possible with a direct method naming query. You can however use the built in sorting mechanism, using the Sort class. The repository has a findAll(Sort) method that you can pass an instance of Sort to. For example:

import org.springframework.data.domain.Sort;

@Repository
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDAO studentDao;

    @Override
    public List<Student> findAll() {
        return studentDao.findAll(sortByIdAsc());
    }

    private Sort sortByIdAsc() {
        return new Sort(Sort.Direction.ASC, "id");
    }
} 
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • 1
    This is indeed possible using findAllByOrderByIdAsc() as mentioned in [Sikor's answer below](http://stackoverflow.com/a/27427359/536358)... @Prashant that really should be the correct answer – Samuel Parsonage Jun 09 '15 at 09:13
  • Alternative way of doing the sort in the service tier if you want to keep your repositories less cluttered. Keep in mind the result size though! – syncdk Mar 05 '16 at 20:04
  • 3
    The method `findAll()` in the type `CrudRepository<>` is not applicable for the arguments (Sort) – Thiago Pereira Jul 06 '16 at 19:25
  • 5
    @ThiagoPereira you should extends `JpaRepository<>` if you wish to use above example. – Waleed Abdalmajeed May 17 '18 at 09:19
58

Simple way:

repository.findAll(Sort.by(Sort.Direction.DESC, "colName"));

Source: https://www.baeldung.com/spring-data-sorting

17

Please have a look at the Spring Data JPA - Reference Documentation, section 5.3. Query Methods, especially at section 5.3.2. Query Creation, in "Table 3. Supported keywords inside method names" (links as of 2019-05-03).

I think it has exactly what you need and same query as you stated should work...

t0r0X
  • 4,212
  • 1
  • 38
  • 34
shlomi33
  • 1,458
  • 8
  • 9
  • 1
    Your link does not work -> I assume you wanted to point towards this link: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods – Jørgen Skår Fischer Sep 05 '15 at 23:21
13

Yes you can sort using query method in Spring Data.

Ex:ascending order or descending order by using the value of the id field.

Code:

  public interface StudentDAO extends JpaRepository<StudentEntity, Integer> {
    public findAllByOrderByIdAsc();   
}

alternative solution:

    @Repository
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDAO studentDao;

    @Override
    public List<Student> findAll() {
        return studentDao.findAll(orderByIdAsc());
    }
private Sort orderByIdAsc() {
    return new Sort(Sort.Direction.ASC, "id")
                .and(new Sort(Sort.Direction.ASC, "name"));
}
}

Spring Data Sorting: Sorting

Narayan Yerrabachu
  • 1,714
  • 1
  • 19
  • 31
7

I try in this example to show you a complete example to personalize your OrderBy sorts

 import java.util.List;
 import org.springframework.data.domain.Page;

 import org.springframework.stereotype.Repository;
 import org.springframework.data.domain.Sort;
 /**
 * Spring Data  repository for the User entity.
 */
 @SuppressWarnings("unused")
 @Repository
 public interface UserRepository extends JpaRepository<User, Long> {
 List <User> findAllWithCustomOrderBy(Sort sort);
 }

you will use this example : A method for build dynamically a object that instance of Sort :

import org.springframework.data.domain.Sort;
public class SampleOrderBySpring{
 Sort dynamicOrderBySort = createSort();
     public static void main( String[] args )
     {
       System.out.println("default sort \"firstName\",\"name\",\"age\",\"size\" ");
       Sort defaultSort = createStaticSort();
       System.out.println(userRepository.findAllWithCustomOrderBy(defaultSort ));
        

       String[] orderBySortedArray = {"name", "firstName"};
       System.out.println("default sort ,\"name\",\"firstName\" ");
       Sort dynamicSort = createDynamicSort(orderBySortedArray );
       System.out.println(userRepository.findAllWithCustomOrderBy(dynamicSort ));
      }
      public Sort createDynamicSort(String[] arrayOrdre) {
        return  Sort.by(arrayOrdre);
        }

   public Sort createStaticSort() {
        String[] arrayOrdre  ={"firstName","name","age","size");
        return  Sort.by(arrayOrdre);
        }
}
Mayuri
  • 18
  • 4
S. FRAJ
  • 91
  • 1
  • 2
1

Combining all answers above, you can write reusable code with BaseEntity:

@Data
@NoArgsConstructor
@MappedSuperclass
public abstract class BaseEntity {

  @Transient
  public static final Sort SORT_BY_CREATED_AT_DESC = 
                        Sort.by(Sort.Direction.DESC, "createdAt");

  @Id
  private Long id;
  private LocalDateTime createdAt;
  private LocalDateTime updatedAt;

  @PrePersist
  void prePersist() {
    this.createdAt = LocalDateTime.now();
  }

  @PreUpdate
  void preUpdate() {
    this.updatedAt = LocalDateTime.now();
  }
}

DAO object overloads findAll method - basically, still uses findAll()

public interface StudentDAO extends CrudRepository<StudentEntity, Long> {

  Iterable<StudentEntity> findAll(Sort sort);

}

StudentEntity extends BaseEntity which contains repeatable fields (maybe you want to sort by ID, as well)

@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
class StudentEntity extends BaseEntity {

  String firstName;
  String surname;

}

Finally, the service and usage of SORT_BY_CREATED_AT_DESC which probably will be used not only in the StudentService.

@Service
class StudentService {

  @Autowired
  StudentDAO studentDao;

  Iterable<StudentEntity> findStudents() {
    return this.studentDao.findAll(SORT_BY_CREATED_AT_DESC);
  }
}
J.Wincewicz
  • 849
  • 12
  • 19
1

for spring boot 3, your Repository should implement JpaRepository and define the sort as follow :

Sort sortBy = Sort.by(Sort.Direction.DESC, "id");

then use it :

repository.findAll(sortBy);
khocef
  • 105
  • 11
0
Sort sortBy = Sort.by(new Sort.Order(Sort.Direction.ASC, "name").ignoreCase());

repository.findAll(sortBy);
Vikcen
  • 153
  • 2
  • 9