JPA Repository에서 지원하지 않는 쿼리를 사용하려면 사용자 정의 쿼리를 구현해야 한다.
사용자 정의 쿼리를 구현하기 위해서는
@Query
를 사용해 사용할 메소드 위에 정의의 두 가지 방법이 있다.
SQL과 JPQL에는 차이점이 있다.
SQL
테이블을 대상으로 쿼리 실행
JPQL
엔티티를 대상으로 쿼리 실행
JPQL에는 몇가지 특징이 있다.
@Entity(name='name')
의 형식으로 지정할 수 있다.d
는 Booktbl
이라는 엔티티의 별칭이다. 이 별칭을 필수적으로 지정해야 한다.JPQL을 실행하기 위한 객체를 만들어야 한다.
TypedQuery
반환 타입이 명확함
Query
반환 타입이 명확하지 않음
예시는 다음과 같다.
@PersistenceContext
private EntityManager em;
//jpql 작성
String jpql = "select d from Booktbl d";
public List<BookDTO> getBookList() {
//쿼리를 실행하기 위한 객체 생성
TypedQuery<BookDTO> query = em.createQuery(jpql, BookDTO.class);
List<BookDTO> bookList = query.getResultList();
return bookList;
}
@Entity (name="Booktbl")
public class BookDTO {
@NotNull
@Id
@GeneratedValue
@Column(name = "idx")
private long idx;
@NotNull
@Column(name = "title")
private String title;
@NotNull
@Column(name = "author")
private String author;
}
@Query는 JPARepository를 상속하는 인터페이스에서 사용한다.
사용자 지정 쿼리를 만들기 위해 파라미터 바인딩을 하는데, 두 가지 방법이 있다.
그리고 테이블 기준으로 쿼리를 작성하기 위해서는 nativeQuery = true
옵션을 주면 된다.
위치 기준 바인딩
JDBC의 ResultSet과 비슷하다. 하지만 위치 기반이기 때문에 위치를 잘못 기재하여 발생하는 오류와 수정이 어렵기 때문에 이름 기준 바인딩을 주로 사용한다.
SELECT m FROM Member m WHERE m.username = ?0
이름 기준 바인딩
파라미터의 이름을 기준으로 바인딩한다.
@Query("select u from User u where u.username = :name")
예시는 다음과 같다.
public interface BookRepository extends JpaRepository<BookDTO, Integer> {
@Query(value = "SELECT * FROM BookTbl", nativeQuery = true)
List<BookDTO> getAllBookList();
@Query(value = "SELECT * FROM Booktbl WHERE idx > :idx", nativeQuery = true)
BookDTO getBookById(long idx);
}