如何在Spring Data中使用OrderBy和findAll?

430

我正在使用Spring Data,我的DAO看起来像这样:

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

在上面的代码中,注释行显示了我的意图。Spring Data是否提供内置功能,以使用此类方法按某个列按ASC / DESC顺序查找所有记录?

9个回答

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

上述代码应该可以正常工作。我正在使用类似的代码:
public List<Pilot> findTop10ByOrderByLevelDesc();

它返回最高级别的10行。 重要提示: 由于我被告知很容易错过这个答案的关键点,所以在此进行一些澄清:
findAllByOrderByIdAsc(); // don't miss "by"
       ^

7
为了让你的方法签名在Spring Data JPA中按预期工作,应该包含“all”关键字,像这样:List<StudentEntity> findAllByOrderByIdAsc();。另外,添加返回类型并删除冗余的public修饰符也是个好主意 ;) - Håvard Geithus
2
我同意public是多余的,但是在别人需要处理你的代码时,它可以使事情清晰明了。你永远不知道将会是谁:P 我没有改变作者代码中方法名称以外的任何东西,因为问题并不在那里,如果有人不知道应该放什么,希望他们能学到一些新东西。此外,在我的下面的示例中,它已经添加了'all'关键字,所以他们不必搜索神知道哪里,但如果您坚持,那就这样吧:) 谢谢。 - Sikor
13
仍然不明白为什么需要在“OrderBy”前面添加额外的“By”。文档没有说明 - Aritz
7
根据您提供的文档链接:“However, the first By acts as delimiter to indicate the start of the actual criteria.” 此外,如果您向下滚动到“3.4.5. Limiting query results”部分,实际上有一个类似的示例,但它没有被解释。 - Sikor
2
@Eduardo 如果您想按两个或更多列排序,只需在asc/desc关键字后面声明另一列,如此:findAllByOrderByFirstcolAscSecondcolDesc(未经测试,但应该可以工作)。但是,如果方法名称变得太长,我建议切换到 findAll(Pageable pageRequest) 并在 Pageable 中传递 Sort 对象,这样更加灵活,因为您不必为每个用途创建单独的方法。这样客户端就可以决定如何排序,需要多少行等。 - Sikor
显示剩余8条评论

71
AFAIK,我认为使用直接的命名查询方法是不可能的。但是你可以使用内置的排序机制,使用 Sort 类。该仓库有一个 findAll(Sort) 方法,您可以向其传递一个 Sort 实例。例如:
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");
    }
} 

1
这确实是可能的,使用findAllByOrderByIdAsc(),如Sikor在下面的回答中提到的... @Prashant那真的应该是正确的答案。 - Samuel Parsonage
如果你想让仓库的代码更加简洁,可以考虑在服务层采用另一种排序方法。但需要注意结果数量的大小! - syncdk
3
CrudRepository<>中的方法findAll()不适用于参数(Sort) - Thiago Pereira
5
如果您希望使用上面的示例,您应该扩展JpaRepository <> - Waleed Abdalmajeed

62

对我有用,谢谢。 - Mugeesh Husain
我正在寻找如何使用参数化顺序进行排序,所以这个答案是最有帮助的。 - ashley

17

1
你的链接无法使用 -> 我猜你想指向这个链接: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods - Jørgen Skår Fischer

14

在Spring Data中,可以使用查询方法进行排序。

例如:使用id字段的值进行升序或降序排列。

代码:

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

备选方案:

    @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数据排序:排序


7

在这个例子中,我尝试向您展示一个完整的示例,以个性化您的OrderBy排序

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

你将会使用这个例子: 动态构建一个排序实例对象的方法:
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);
        }
}

2

对于Spring Boot 3,您的Repository应该实现JpaRepository并按照以下方式定义排序:

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

然后使用它:

repository.findAll(sortBy);

1
Sort sortBy = Sort.by(new Sort.Order(Sort.Direction.ASC, "name").ignoreCase());

repository.findAll(sortBy);

1

结合以上所有回答,您可以使用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对象重载了findAll方法 - 基本上,仍然使用findAll()

public interface StudentDAO extends CrudRepository<StudentEntity, Long> {

  Iterable<StudentEntity> findAll(Sort sort);

}

StudentEntity继承了BaseEntity,其中包含可重复的字段(也许您想按ID排序)

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

  String firstName;
  String surname;

}

最后,SORT_BY_CREATED_AT_DESC 的服务和使用可能不仅限于 StudentService
@Service
class StudentService {

  @Autowired
  StudentDAO studentDao;

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

非常好的干净答案! - sebasira
StudentDAO 应该继承 JpaRepository,这样你就不需要声明 findAll(Sort sort) 方法。 - Esteban

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接