Programming/Spring

[JPA] 랜덤값 가져오기

Ry- 2024. 9. 29. 21:08

프로젝트를 진행 중에 사용자의 테마를 기준으로 랜덤 데이터 값을 가져오는 기능을 만들어야 했다.

 

어떻게 구현을 해야 하는지 고민을 해보았다.

기본적으로 JPA는 랜덤으로 데이터를 추출하는 기능은 없다고 한다.

 

그래서 2가지 방법을 기본적으로 사용을 한다고 하는데

첫 번째 방식은 페이징 방식이다. 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
public class BookService {

    @Autowired
    private BookRepository bookRepository;

    public List<BookDAO> getRandomBooks(int pageSize) {
        // 1. 전체 데이터 수 가져오기
        long totalCount = bookRepository.count();
        
        // 2. 랜덤 페이지 번호 생성 (0부터 총 페이지 수 - 1)
        int totalPages = (int) (totalCount / pageSize);
        Random random = new Random();
        int randomPage = random.nextInt(totalPages + 1);

        // 3. 페이징 쿼리 실행
        Pageable pageable = PageRequest.of(randomPage, pageSize);
        Page<BookDAO> bookPage = bookRepository.findAll(pageable);
        
        return bookPage.getContent();
    }
}

이런식으로 작성을 할 수 가 있다.

다른 방식으로는 

네이티브 쿼리 방식이다

@Query(value = "SELECT * FROM book ORDER BY RAND() LIMIT :limit", nativeQuery = true)
List<BookDAO> findRandomBooks(@Param("limit") int limit);

 

여기서 nativeQuery = true를 진행을 해야지만 네이티브 쿼리 방식으로 작성 할 수 있다.

 

여기서 나는 

@Query("SELECT b FROM BookDAO b WHERE b.theme IN :theme AND b.bookid BETWEEN 0 AND 16")
    List<BookDAO> findByThemeAndBookIdRange(List<String> theme);

이렇게 작성을 하여 bookid의 범위가 0부터 16 까지의 범위에서 알맞은 테마만 추출 하도록 하였다.

 

위에서 봤던 페이징 방식을 사용하지 않은 이유는 나는 데이터를 3가지만 추출 하면 되기 때문이다.

페이징은 많은 데이터를 랜덤으로 뽑아낼때 효율성이 좋고 성능 저하를 최소화 할 수 있는 방식이라고 한다.

 

 

출처 - 

https://velog.io/@yangwon-park/JPA%EC%97%90%EC%84%9C%EC%9D%98-%EB%9E%9C%EB%8D%A4-%EB%A0%88%EC%BD%94%EB%93%9C-%EC%A1%B0%ED%9A%8C-%EB%B0%A9%EB%B2%95