使用Spring数据JPA获取随机记录

时间:2014-06-18 07:11:53

标签: spring hibernate jpa spring-data spring-data-jpa

我想使用Spring数据JPA获取随机记录。我正在使用@Query。但这需要很长时间。

@Query("select que from Question que order by RAND()")
public List<Question> findRandamQuestions();

这样做的有效方法是什么?请帮忙!

3 个答案:

答案 0 :(得分:15)

select que from Question que order by RAND()的问题是您的数据库会在返回一个项目之前订购所有记录。所以它在大型数据集中很昂贵。

实现这一目标的更便宜的方法包括两个步骤:

  1. 查找您将从中选择一条记录的总记录。
  2. 在此集中获取一个随机项目。
  3. 例如,要在MySql中执行此操作,您可以执行以下操作:

    select count(*) from question;
    
    // using any programming language, choose a random number between 0 and count-1 (let's save this number in rdn), and finally
    
    select * from question LIMIT $rdn, 1;
    

    好的,但要在spring数据中执行此操作,您需要创建一些本机查询...

    幸运的是,我们可以使用分页来解决这个问题。在您的存储库接口中,创建方法(某些存储库具有此功能而无需定义它):

    Long count(); 
    Page<Question> findAll(Pageable pageable);
    

    在您的服务中,您可以通过以下方式使用您的存储库:

    public Question randomQuestion() {
        Long qty = questionRepository.countAll();
        int idx = (int)(Math.random() * qty);
        Page<Question> questionPage = questionRepository.findAll(new PageRequest(idx, 1));
        Question q = null;
        if (questionPage.hasContent()) {
            q = questionPage.getContent().get(0);
        }
        return q;
    }
    

答案 1 :(得分:3)

你可以在获取后进行此操作。

获取所有问题的清单,然后从中获取随机问题。

public List<Question> getRandomQuestions(List<Questions> questions, int numberOfQuestions) {
    List<Question> randomQuestions = new ArrayList<>();
    List<Question> copy = new ArrayList<>(questions);

    SecureRandom rand = new SecureRandom();
    for (int i = 0; i < Math.min(numberOfQuestions, questions.size()); i++) {
        randomQuestions.add( copy.remove( rand.nextInt( copy.size() ) );
    }

    return randomQuestions;
}

或者,如果您的列表非常大并且您事先知道了ID,那么您可以执行相同的操作,只需获取所需的问题ID。

答案 2 :(得分:0)

AFAIK在Spring Data中不支持此功能。恕我直言,你最好的做法是创建一个原生查询,例如@Query(nativeQuery=true, value="SELECT * FROM question ORDER BY random() LIMIT 10")使用PostgreSQL的本地random()排序方法,或者数据库中的某些等效方法。