2014-06-18 109 views
9

我想使用Spring數據JPA獲取隨機記錄。我正在使用@Query,但它需要很長時間。使用Spring數據獲取隨機記錄JPA

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

這是做同樣的有效方法嗎?請幫助!

回答

3

你可以做這個post fetch。

獲得所有問題的列表,只是從那些隨機的問題。

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。

0

AFAIK在Spring Data中沒有對此的支持。恕我直言,你最好的行動方式是創建一個本地查詢,例如@Query(nativeQuery=true, value="SELECT * FROM question ORDER BY random() LIMIT 10")使用PostgreSQL的原生random()排序方法,或在您的數據庫中的一些等價物。

5

select que from Question que order by RAND()的問題在於您的數據庫將在返回一個項目之前對所有記錄進行排序。所以它在大數據集中很昂貴。

便宜的方式來實現這一目標包括兩個步驟:

  1. 查找總記錄:從那裏你會選擇一個。
  2. 獲得一組隨機項目。

要做到這一點比如在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; 

好,但要做到這一點,春季數據,你需要創建一些原生查詢...

幸運的是,我們可以使用分頁來解決這個問題。在您的倉庫接口,創建方法(某些存儲庫有此無需將它定義):

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; 
} 
+0

這是一個(a)它*完全*我所需要的,以及(b)谷歌和我無法發現任何其他遠程關閉的完美答案。但我認爲你有一個錯字:不應該「countAll()」是「count()」? – fivedogit