정렬 정보를 전달, 정렬 정보는 필드이름, 정렬방향의 포맷으로 전달한다. 여러 필드를 순차적으로 정렬도 가능하다. (sort=createdAt,desc&sort=userId,asc)
아래는 위 Controller를 통해 HTTP요청으로 페이징과 정렬된 데이터를 전달받는 URI 샘플이다.
GET /users?page=1&size=10&sort=createdAt,desc&sort=userId,asc
조회 전용 기능 구현
리포지터리는 여러 애그리거트를 조합하여 데이터를 제공하거나 각종 통계 데이터를 제공하는 것은 적합하지 않다. 이러한 기능은 조회 전용 쿼리로 처리해야 한다. JPA와 하이버네이트를 사용하면 동적 인스턴스 생성, @Subselect확장 기능, 네이티브 쿼리를 이용하여 조회 전용 기능을 구현할 수 있다.
동적 인스턴스 생성
JPQL에서 동적 인스턴스를 사용한 코드
코드에서 JPQL의 select 절에는 new 키워드가 있다. new 키워드 뒤에 생성할 인스턴스의 완전한 클래스 이름을 지정하고 괄호 안에 생성자에 인자로 전달할 값을 지정한다. 이 코드는 OrderView 생성자에 각각 Order, Member, Product를 전달하고 생성자는 전달받은 객체로 부터 필요한 값을 추출한다. 이런 방법 이외에 모델의 개별 프로퍼티를 생성자에 전달할 수도 있다.
동적 인스턴스의 장점은 JPQL을 그대로 사용하므로 객체 기준으로 쿼리를 작성하면서도 지연/즉시 로딩과 같은 고민 없이 원하는 모습으로 데이터를 조회할 수 있다는 점이다.
하이버네이트의 @Subselect 사용
하이버네이트는 JPA의 확장 기능으로 쿼리 결과를 @Entity로 매핑할 수 있는 @Subselect를 제공한다.
@Immutable , @Subselect, @Synchronize는 하이버네이트 전용 어노테이션으로 이 태그를 사용하면 테이블이 아닌 조회(select) 쿼리 결과를 @Entity로 매핑할 수 있다.
@Immutable
뷰를 수정할 수 없듯이 @Subselect로 조회한 @Entity도 수정할 수 없다. 이를 보장하기 위해 @Immutable을 사용한다.
@Synchronize
@Synchonize는 해당 엔티티와 관련된 테이블 목록을 명시한다. 하이버네이트는 엔티티를 로딩하기 전에 지정한 테이블과 관련된 변경이 발생하면 플러시를 먼저한다. 따라서 OrderSummary를 로딩하는 시점에는 변경 내역이 반영된다.
@Subselect
@Subselect는 값으로 지정한 쿼리를 from 절의 서브 쿼리로 사용한다. 서브 쿼리를 사용하고 싶지 않다면 네이티브 SQL을 사용하거나 MyBatis와 같은 별도 매퍼를 사용해서 조회 기능을 구현해야 한다.