본문 바로가기
학습/DB

Native Query

코동이 2021. 9. 30.

Native Query는 JPA와 무관하게, 실제 DB 쿼리문을 작성할 때 사용된다.

@Query 맨 뒤에 nativeQuery=true라고 설정만 해주면 된다.

또한 엔티티를 조회하던 JPQL 문법과 달리 DB에서 사용하는 테이블 기준 쿼리를 작성하면 된다.

 

@Query(value = "select * from book" , nativeQuery = true)
List<Book> findAllCustom();

 

 

@Test
void nativeQeuryTest() {
 booKRepository.findAll().forEach(System.out::println);
 bookRepository.findAllCustom().forEach(System.out::println);
}

 

@Query 메서드는 @Where을 감지해서 실행하지만,  NativeQuery에서는 @Where가 포함되어 있지 않는다. 

 

NativeQuery는 되도록이면 사용하지 않는데, DB에 따라서 실행이 안될 수 있다. 

 

JPA에서는 deleteAllInBatch() 는 delete from book; 으로 한번에 삭제가 가능하다.

하지만, update는 한번에 가능하지 않고, 하나씩 save()를 해주어야 한다. 이럴 때 NativeQuery를 사용한다.

 

List<Book> books = bookRepository.findAll();

for(Book book : books) {
  book.setCategory("IT서적");
}

bookRepository.saveAll(books);

 

book을 업데이트하기 위해서는 for문으로 하나씩 조회해서 업데이트를 해야 한다.

몇천만건을 한번에 가져와서 처리하는 것은 성능이슈가 있을 수 있다. 따라서 한번에 처리하는 것이 좋다. Native Query를 사용하면 된다.

 

 

public interface BookRepository extends JpaRepository<Book, Long> {
...
@Transactional
@Modifying
@Query(value = "update book set category = 'IT서적'", nativeQuery = true)
int updateCategories();
...
}

 

nativeQuery의 경우 트랜잭션을 직접 설정해주어야 하므로 @Transactional을 사용한다. 또한 @Modifying으로 업데이트라는 것을 알려준다. nativeQuery이므로 엔티티를 조회하는 것이 아니라, 테이블을 기준으로 작동한다. 리턴형이 int이면 업데이트 된 횟수를 리턴한다. 

 

 

@Test
public void update() {
List<Book> books = bookRepository.findAll();

bookRepository.updateCategories();
}

 

nativeQuery로 하면 save()가 1개씩 모두 쿼리를 날렸던 것과 달리 하나의 쿼리만 나간다. (여전히 @Where는 무시한다.)

 

스프링 공식문서에는 구체적인 클래스, 혹은 구체적인 클래스의 메서드에 @Transactional을 사용하는 것을 권고한다. 혹은 인터페이스에 선언하고 싶다면 updateCategories()와 같이 프록시 interface에 정의한다.

 

 

마지막으로는 실제 사용하는 곳에서 @Transactional을 선언해야 한다.

 

@Transactional
@Test
public void update() {
List<Book> books = bookRepository.findAll();

bookRepository.updateCategories();
}

 

 

일반적인 JPA에서 제공하지 않는 정보들을 nativeQuery로 조회할 수 있다.

 

@Query(value = "show tables", nativeQuery = true)
List<String> showTables();

 

 

DB의 테이블 정보들을 조회할 수 있다.

 

@Test
public void showTables() {
 bookRepository.showTables();
}

 

 

*정리

native Query는 JPA에서 제공하지 않는 정보들을 조회할 수 있고 update를 한번에 처리할 수 있는 장점이 있다. 하지만, 대부분 운영에서는 잘 사용하지 않기 때문에 대부분 쿼리는 JPA로 해결한다.

반응형

'학습 > DB' 카테고리의 다른 글

Converter 사용하기  (0) 2021.09.30
@Embedded, @Embedabble  (0) 2021.09.30
@Transactional  (0) 2021.09.26
고아제거 속성 알아보기  (0) 2021.09.26
Cascade 활용하기  (0) 2021.09.26