Cómo usar OrderBy con findAll en Spring Data

288

Estoy usando datos de primavera y mi DAO parece

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

En el código anterior, la línea comentada muestra mi intención. ¿Puede Spring Data proporcionar una funcionalidad incorporada para usar dicho método para encontrar todos los registros ordenados por alguna columna con ASC / DESC?

Prashant Shilimkar
fuente

Respuestas:

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

El código anterior debería funcionar. Estoy usando algo similar:

public List<Pilot> findTop10ByOrderByLevelDesc();

Devuelve 10 filas con el nivel más alto.

IMPORTANTE: Como me han dicho que es fácil pasar por alto el punto clave de esta respuesta, aquí hay una pequeña aclaración:

findAllByOrderByIdAsc(); // don't miss "by"
       ^
Sikor
fuente
44
Para su método de firma funcione como se pretende con la primavera de datos JPA, debe incluir el "todo" de palabras clave, así: List<StudentEntity> findAllByOrderByIdAsc();. Agregar un tipo de retorno y eliminar el modificador público redundante también es una buena idea;)
Håvard Geithus
1
Estoy de acuerdo en que public es redundante, pero mantiene las cosas claras en caso de que alguien más tenga que trabajar en su código. Nunca se sabe quién será: PI no cambió nada más que el nombre del método en el código de los autores porque no es dónde estaba el problema y si alguien no sabe qué debería estar allí, con suerte aprenderá algo nuevo. Además, está en mi ejemplo a continuación para que no tengan que buscar Dios sabe dónde, pero si insistes, que así sea :) Se agregó la palabra clave 'todos'. Gracias.
Sikor
73
Tenga en cuenta que poco Byantes de la OrderBypalabra clave hace toda la diferencia.
Stefan Haberl
55
Todavía no entiendo por qué es necesario agregar un extra Byal frente OrderBy. La documentación no dice nada al respecto .
Xtreme Biker
3
@XtremeBiker Desde el enlace de documentación que proporcionó: "Sin embargo, el primer By actúa como delimitador para indicar el inicio de los criterios reales". Además, si se desplaza hacia abajo hasta la sección "3.4.5. Limitar los resultados de la consulta", en realidad hay un ejemplo como este, pero no se explica.
Sikor
54

AFAIK, no creo que esto sea posible con una consulta de nomenclatura de método directo. Sin embargo, puede usar el mecanismo de clasificación incorporado, usando la Sortclase. El repositorio tiene un findAll(Sort)método al que puede pasar una instancia Sort. Por ejemplo:

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
fuente
De hecho, esto es posible usando findAllByOrderByIdAsc () como se menciona en la respuesta de Sikor a continuación ... @Prashant esa debería ser la respuesta correcta
Samuel Parsonage
Una forma alternativa de hacer la clasificación en el nivel de servicio si desea mantener sus repositorios menos abarrotados. ¡Tenga en cuenta el tamaño del resultado!
dkanejs
2
El método findAll()en el tipo CrudRepository<>no es aplicable para los argumentos (Ordenar)
Thiago Pereira
55
@ThiagoPereira debe extender JpaRepository<>si desea utilizar el ejemplo anterior.
Waleed Abdalmajeed
15

Consulte la JPA de Spring Data: documentación de referencia, sección 5.3. Métodos de consulta , especialmente en la sección 5.3.2. Creación de consultas , en la " Tabla 3. Palabras clave admitidas dentro de los nombres de los métodos " (enlaces a partir del 2019-05-03).

Creo que tiene exactamente lo que necesitas y la misma consulta que dijiste debería funcionar ...

shlomi33
fuente
1
Su enlace no funciona -> Supongo que quería señalar hacia este enlace: docs.spring.io/spring-data/jpa/docs/current/reference/html/…
Jørgen Skår Fischer
3

Sí, puede ordenar utilizando el método de consulta en Spring Data.

Ej: orden ascendente u orden descendente utilizando el valor del campo id.

Código:

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

solución alternativa:

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

Clasificación de datos de primavera: clasificación

Narayan Yerrabachu
fuente
3

Intento en este ejemplo mostrarle un ejemplo completo para personalizar su orden

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

usará este ejemplo: Un método para construir dinámicamente un objeto que instancia de Ordenar:

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
fuente
0

Combinando todas las respuestas anteriores, puede escribir código reutilizable con 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();
  }
}

El objeto DAO sobrecarga el método findAll - básicamente, todavía usa findAll()

public interface StudentDAO extends CrudRepository<StudentEntity, Long> {

  Iterable<StudentEntity> findAll(Sort sort);

}

StudentEntityse extiende, BaseEntityque contiene campos repetibles (tal vez también desee ordenar por ID)

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

  String firstName;
  String surname;

}

Finalmente, el servicio y el uso de los SORT_BY_CREATED_AT_DESCcuales probablemente se utilizarán no solo en el StudentService.

@Service
class StudentService {

  @Autowired
  StudentDAO studentDao;

  Iterable<StudentEntity> findStudents() {
    return this.studentDao.findAll(SORT_BY_CREATED_AT_DESC);
  }
}
J.Wincewicz
fuente