🌿SPRING/🍀공부 [SPRING]

[SPRING][JPA] native query 활용하기

디카페인라떼 2022. 9. 29. 16:37

패스트 캠퍼스의 강의 [한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지]를 보고 정리한 글입니다.


사용 방법 및 특징
  • @Query(nativeQuery = true) 로해주면 사용가능
@Query(value = "select * from book", nativeQuery = true)
 List<Book> findAllCustom();
  • JPQL과 다르게 entity 속성을 사용하지 못함 
    • Entity 명이 아닌 table 명을 써야함!
    • * 이아니라 속성값을 넣어야 한다면 컬럼명을 기록해야함!
      • ex)createdAt 이아닌 created_at (컬럼명)
  • 기본적으로 JPQL 쿼리들은 alias들이 걸림 (별칭)
    • delete 값이 안나옴
  • nativeQuery는 기록해준 것들만 나옴.
    • 레코드 값이 모두 나옴
  • => Entity에 선언한 @where 이 쿼리메소드에는 포함되어있지만 nativeQuery에서는 포함되어 있지 않음
  • => nativeQuery는 DB에서 사용하는  SQL쿼리를 그대로 사용
    •  쿼리문에 적은 text가 그대로 실행
    •  방언을 활용하지 않기 때문에 특정 DB에 의존성을 가진 쿼리 생성
      • (방언 : 서로다은 DB 간의 SQL 문법 차이)
    • 즉 DB종류가 변경되었을 때 코드변경없이 쿼리를 자동으로 바꿔주는 JPA 장점에서 떨어진 기능
    •  사실 현업에서는 DB 머신을 바꾸는 경우가 적음. 특히 이종 DB로 바꾸는 건 더 희귀
    • 운영 DB는 Mysql같은거 Test 코드는 H2를 많이 사용 즉 테스트와 운영환경에서 이종 DB를 사용하게 됨. => 일부 특수경우 오작동 가능성
    • 🚩즉 nativeQuery를 최소한으로 쓰는 게 좋음

 

nativeQuery를 쓰는 이유?
  1. 성능에 대한 문제 해결
    •  JPA의 제공 메소드 중 
      • deleteAllInBatch => 조건없이 delete from book으로 모두 삭제됨
      • deleteAll => findAll을 한 다음 각 레코드의 id 값으로 삭제를 진행함.
        • 즉, delete쿼리의 경우 모든 레코드를 조회하지 않아도 한번에 처리할 수 있는 메소드를 제공
      • update 쿼리는 그렇지 않고 하나하나 조회해서 id값을 가져와서 처리함. => 대량의 DB의 경우 속도 저하, 성능 이슈가 생김.
      • 한번의 쿼리로 실행할 수 있게 하기 위해서 nativeQuery를 사용함!
        •  
@Transactional
@Modifying <- insert/update/delete 작업 (DML)이라는 것을 알려줌! (select 제외)
* @Modifying (clearAutomatically = true) @Query로 정의 된 JPQL을 실행후에 자동으로 영속성 컨텍스트를 비워주는 옵션. true로 해주어야 DB에서 가져온 데이터들이 영속성 컨덱스트에 저장되어 최신상태 유지가능
@Query(value = "update book set category = 'IT 전문서'", nativeQuery = true)
int updateCategories();
      • => affected row : 업데이트된 row의 수를 반환 받음-> 삭제된 레코드까지 업데이트함. 
        • **Interface에 선언된 @Transactional
          • 인터페이스보다는 구체 클래스에 사용하는 걸 권고.
          •  인터페이스에서는 인터페이스 베이스 프록시에서만 사용
          •  취향에 따라서 원하는 곳에 선언하기..
  1. JPA에서 기본적으로 지원하지 않는 기능들을 사용할 때
    - 굳이 java로 만들어야 하나? 하는 경우 
@Query(value = "show tables", nativeQuery = true)
List<String> showTables();

 

-> value에 있는 문자열이 그대로 실행되기 때문에 특수한 형태의 쿼리들도 실행 가능함.


🚩JPA에서 nativeQuery를 사용하는 것은 최소한 국소적으로 하는걸 추천