@NamedNativeQuery 결과 POJO에 매핑
JPQL에 사용할수 없는 기능들이 있는데 그 중 하나가 UNION
기능이다. 이를 보완하기 위해 @NamedNatvieQuery
를 이용해 Natvie 쿼리를 사용할 수 있게 지원한다.
예제
먼저 사용된 예제를 살펴보자. 추출 목적은 STUDENT 테이블과 TEACHER 테이블의 데이터를 한번에 보여주고 싶다.
@Data
@NamedNativeQuery(
name = "Person.methodNameInRepository",
query = "SELECT s.id, s.name, s.phone, s.address FROM STUDENT s WHERE s.class_number = (?1) " +
"UNION " +
"SELECT t.id, t.name, t.phone, t.address FROM TEACHER t WHERE t.class_number = (?1)",
resultSetMapping = "personProfileMapper"
)
@SqlResultSetMapping(
name = "personProfileMapper",
classes = {@ConstructorResult(
targetClass = PersonDto.class,
columns = {
@ColumnResult(name = "id"),
@ColumnResult(name = "name"),
@ColumnResult(name = "phone"),
@ColumnResult(name = "address")
}
)}
)
@NamedNativeQuery 속성
- name : 이름. 뒤에 붙는 메소드 이름(methodNameInRepository)과 @Repository 인터페이스에서 선언할 함수의 이름은 동일해야한다.
- query : 사용할 쿼리. JPQL 문법이 아닌 각 벤더에 맞는 쿼리를 그대로 사용한다. 클래스에 선언한 Entity 속성들이 아닌 아닌 테이블이름 및 컬럼명을 사용해야한다. 여기에 입력한 쿼리 내용이 그대로 JDBC로 전달된다.
- resultSetMapping : 쿼리 결과를 객체에 어떻게 담을지 설정하는
@SqlResultSetMapping
의 이름을 명시.@SqlResultSetMapping
은 아래에서 설명한다.
POJO에 쿼리 결과 바인딩
JPA 2.1 이전에는 쿼리의 결과를 반드시 엔티티(@Entity) 객체에 담아야 했다. 하지만 JPA 2.1이후로 POJO에도 객체 생성자를 이용해서 결과값을 담을 수 있다.
- @SqlResultSetMapping
쿼리 결과를 객체에 어떻게 담을지 설정
- name : 매퍼 이름
- classes : 결과값을 저장할 타겟 객체 관련 설정.
@ContructorResult
를 이용해 설정한다. (JPA 2.1에 추가된 기능)
- @ConstructorResult
쿼리 결과를 객체 생성자를 이용해 저장 (JPA 2.1에 추가)
- targetClass : 결과를 저장할 클래스 명시
- columns : 쿼리로 조회한 컬럼 중 객체에 바인딩할 컬럼 명시. 필수값이다!
@ColumnResult
를 사용해 결과를 저장할 컬럼들을 명시한다.
주의사항
위에 @ConstructorResult
에 columns
들을 명시할때 순서에 주의해야 한다. columns속성의 순서와 사용하고자 하는 생성자의 파라미터 갯수 및 순서가 일치해야 한다(변수명은 동일하지 않아도 된다) 그렇지 않을경우 엉뚱할 속성에 값이 바인딩 되거나 "Could not locate appropriate constructor on class" 같은 에러 메세지가 튀어나온다.
참고
https://stackoverflow.com/questions/13012584/jpa-how-to-convert-a-native-query-result-set-to-pojo-class-collection
댓글