Native Query 사용해보자.
@Query(value = "select * from book", nativeQuery = true)
List<Book> findAllCustom(); //
@Transactional
@Modifying
@Query(value = "update book set category = 'IT전문서'", nativeQuery = true)
int updateCategories();
@Query(value = "show tables", nativeQuery = true)
List<String> showTables();
- 네이티브 쿼리는 JPQL과 다르게 Entity 속성들을 사용하지 못합니다.
- select * from book 와 같이 테이블 이름이 들어간다. 다른 컬럼 이름을 적을때도 DB Table에서 쓰는 컬럼 이름을 적어야 한다.
@Test
void nativeQueryTest() {
// bookRepository.findAll().forEach(System.out::println);
// bookRepository.findAllCustom().forEach(System.out::println);
List<Book> books = bookRepository.findAll();
for (Book book : books) {
book.setCategory("IT전문서");
}
bookRepository.saveAll(books);
System.out.println(bookRepository.findAll());
System.out.println("affected rows : " + bookRepository.updateCategories());
bookRepository.findAllCustom().forEach(System.out::println);
System.out.println(bookRepository.showTables());
}
- 현업에서는 네이티브 쿼리를 최소한으로 하는게 좋다. 운영중이나 Test 중에 오류가 생길수도 있기 때문이다. 그럼 네이티브 쿼리는 언제쓸까?
- 첫번째는, 성능 이슈가 존재할때 쓴다. deleteAll쿼리가 모든 컬럼을 조회해서 하나하나씩 지우는 성능 이슈가 있었다. 그래서 나온게 deleteAllInBatch나 deleteInBatch이다. 하지만 update 쿼리는 없다. 그래서 하나하나 조회해서 update해야한다. 위 코드의 books를 불러와서 하나하나 "IT전문서" 카테고를 붙이면 성능이슈가 발생할 것이다. 그래서 deleteAllInBatch같이 한번에 할수있는 쿼리 ("update book set category = 'IT전문서'") 라고 해주면 된다. 이럴때 Native쿼리가 유용하다.
- 이때 중요한건 DML작업에서는 @Modufying이라고 해서 update쿼리라고 표시해줘야한다.
- 또한 Transaction이 필요하다. Native쿼리는 @Transactional을 직접 선언해 줘야 한다.
- 하지만 @Transactional은 Spring에서 인터페이스보다 구체 클래스에 @Transactional을 다는걸 지향한다.
- 두번째는, JPA에서 기본적으로 지원하지 않는 기능을 사용할때 쓴다. 위에있는 List showTables(); 같은 경우가 그렇다. 그럼 특수한 형태의 쿼리도 조회할수 있다.