Jak korzystać z OrderBy z findAll in Spring Data

288

Używam danych wiosennych i wygląda na to moje DAO

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

W powyższym kodzie skomentowany wiersz pokazuje moją intencję. Czy Spring Data zapewnia wbudowaną funkcjonalność do korzystania z takiej metody wyszukiwania wszystkich kolejności rekordów według kolumny według ASC / DESC?

Prashant Shilimkar
źródło

Odpowiedzi:

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

Powyższy kod powinien działać. Używam czegoś podobnego:

public List<Pilot> findTop10ByOrderByLevelDesc();

Zwraca 10 wierszy o najwyższym poziomie.

WAŻNE: Ponieważ powiedziano mi, że łatwo przeoczyć kluczowy punkt tej odpowiedzi, oto małe wyjaśnienie:

findAllByOrderByIdAsc(); // don't miss "by"
       ^
Sikor
źródło
4
W metodzie podpis do pracy zgodnie z przeznaczeniem danych z wiosennej WZP, należy uwzględnić „wszystkie” słowa kluczowego, tak jak: List<StudentEntity> findAllByOrderByIdAsc();. Dobrym pomysłem jest również dodanie typu zwrotu i usunięcie zbędnego publicznego modyfikatora;)
Håvard Geithus
1
Zgadzam się, że public jest zbędny, ale zapewnia przejrzystość na wypadek, gdyby ktoś musiał popracować nad twoim kodem. Nigdy nie wiadomo, kto to będzie: PI nie zmienił niczego poza nazwą metody w kodzie autora, ponieważ nie na tym polegał problem, a jeśli ktoś nie wie, co powinno być, mam nadzieję, że nauczy się czegoś nowego. Poza tym, jest to w moim przykładzie poniżej, aby nie musieli szukać boga, który wie, ale jeśli nalegasz, niech tak będzie :) Dodano słowo kluczowe „wszystko”. Dzięki.
Sikor
73
Pamiętaj, że Bytuż przed OrderBysłowem kluczowym robi różnicę.
Stefan Haberl
5
Nadal nie rozumiem, dlaczego konieczne jest dodanie dodatkowych Byz przodu OrderBy. Dokumentacja nie mówi o tym .
Xtreme Biker
3
@XtremeBiker Z podanego linku do dokumentacji: „Jednak pierwszy By działa jak separator wskazujący początek rzeczywistych kryteriów”. Ponadto, jeśli przewiniesz w dół do sekcji „3.4.5. Ograniczanie wyników zapytań”, w rzeczywistości istnieje taki przykład, ale nie został on wyjaśniony.
Sikor
54

AFAIK, nie sądzę, że jest to możliwe przy bezpośrednim zapytaniu o nazwę metody. Możesz jednak użyć wbudowanego mechanizmu sortowania, używając Sortklasy. Repozytorium ma findAll(Sort)metodę, do której można przekazać instancję Sort. Na przykład:

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
źródło
Jest to rzeczywiście możliwe przy użyciu findAllByOrderByIdAsc (), jak wspomniano w odpowiedzi Sikora poniżej ... @Prashant, która naprawdę powinna być poprawną odpowiedzią
Samuel Parsonage
Alternatywny sposób wykonywania sortowania w warstwie usług, jeśli chcesz, aby repozytoria były mniej zagracone. Pamiętaj jednak o wielkości wyniku!
dkanejs
2
Metoda findAll()tego typu CrudRepository<>nie ma zastosowania do argumentów (Sort)
Thiago Pereira
5
@ThiagoPereira powinieneś przedłużyć, JpaRepository<>jeśli chcesz skorzystać z powyższego przykładu.
Waleed Abdalmajeed
15

Proszę spojrzeć na JPA Spring Data - Dokumentacja referencyjna, sekcja 5.3. Metody zapytania , szczególnie w sekcji 5.3.2. Tworzenie zapytania , w „ Tabeli 3. Obsługiwane słowa kluczowe w nazwach metod ” (linki na dzień 03.05.2019).

Myślę, że ma dokładnie to, czego potrzebujesz i takie samo zapytanie, jak podałeś, że powinno działać ...

shlomi33
źródło
1
Twój link nie działa -> Zakładam, że chciałeś wskazać ten link: docs.spring.io/spring-data/jpa/docs/current/reference/html/…
Jørgen Skår Fischer
5

Prosta droga:

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

Źródło: https://www.baeldung.com/spring-data-sorting

TizonDife Villiard
źródło
Istnieją 2 takie same odpowiedzi. Twoja odpowiedź miała niepoprawną formę
Dred
3

Tak, możesz sortować za pomocą metody zapytania w Spring Data.

Np .: kolejność rosnąca lub malejąca przy użyciu wartości pola id.

Kod:

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

alternatywne rozwiązanie:

    @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"));
}
}

Wiosenne sortowanie danych: Sortowanie

Narayan Yerrabachu
źródło
3

W tym przykładzie staram się pokazać pełny przykład personalizacji rodzajów zamówień

 import java.util.List;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.repository.*;
 import org.springframework.data.repository.query.Param;
 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);
 }

użyjesz tego przykładu: Metoda do dynamicznego budowania obiektu, który wystąpienie 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);
        }
}
S. FRAJ
źródło
0

Łącząc wszystkie powyższe odpowiedzi, możesz napisać kod wielokrotnego użytku za pomocą 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();
  }
}

Obiekt DAO przeciąża metodę findAll - w zasadzie nadal używa findAll()

public interface StudentDAO extends CrudRepository<StudentEntity, Long> {

  Iterable<StudentEntity> findAll(Sort sort);

}

StudentEntityrozszerza, BaseEntityktóry zawiera powtarzalne pola (być może chcesz również sortować według identyfikatora)

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

  String firstName;
  String surname;

}

Wreszcie, usługi i korzystanie z SORT_BY_CREATED_AT_DESCktórych prawdopodobnie będą wykorzystywane nie tylko w StudentService.

@Service
class StudentService {

  @Autowired
  StudentDAO studentDao;

  Iterable<StudentEntity> findStudents() {
    return this.studentDao.findAll(SORT_BY_CREATED_AT_DESC);
  }
}
J.Wincewicz
źródło