querydsl은 from절 서브쿼리를 지원하지 않아 답답한 적이 많았는데 다음 방법으로 from절 서브쿼리를 사용해보자.
하이버네이트 @Subselect를 이용해서 서브 쿼리로 사용할 엔티티에 가상 view 처럼 사용하는 것이다. 그렇게 되면 native query로 작성하는 것처럼 사용이 가능하다. 아래는 @Subselect 사용예제이다
subquery용 entity생성
@Entity
@Subselect(
"select * " +
"from VERSION " +
"where VERSION_ID in " +
"( " +
"select max(SW_RELS_NUM) " +
"from VERSION " +
"where CRT_DT in " +
"( " +
"select max(CRT_DT) " +
"from VERSION " +
"group by APP_ID " +
") " +
"group by APP_ID " +
")"
)
@Immutable
@Synchronize("VERSION")
public class SubQuery {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "VERSION_ID", nullable = false)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "APP_ID")
private App app;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "VERSION_FILE")
private File file;
}
(주의할 점은 @Column 에서 정의한 컬럼 명과 @SubSelect 에서 정의한 컬럼이 일치해야 정상적으로 동작한다)
어노테이션
- @Immutable, @Subselect, @Synchronize는 하이버네이트 전용 어노테이션으로 쿼리 결과를 @Entity로 매핑
@Subselect는 조회 쿼리를 값으로 갖는다. - @Immutable은 변경 내용을 방지하기 위해 사용한다. (해당 엔티티의 필드/프로퍼티가 변경되어도 반영 무시)
- @Synchronize는 @Subselect가 만든 view에 접근하기 위한 테이블을 정의
(출처: https://hesh1232.tistory.com/155 )
reposiotry querydsl
위에서 생성한 엔티티를 Q클래스로 생성 후 사용하고자 하는 from 절에 넣어주면
위에서 정의된 쿼리를 from절에서 사용할 수 있다.
// 서브쿼리 선언
QSubQuery subQuery = new QSubQuery("subQuery");
...
AppResponse result = jpaQueryFactory.select(
new QAppResponse(
app.id,
new QVersionResponse(
version.id,
new QFileResponse(
file.id,
file.flExtn,
file.flPath,
).skipNulls()
)
)
)
.from(app)
.leftJoin(subQuery).on(app.id.eq(subQuery.app.id))
.leftJoin(subQuery.file, file)
.where(keywordNull(keywordName, keyword))
.where(eqAll(type))
.fetch();
...
결국 from 서브쿼리는 사용하지 않았다.
'Spring Boot > Spring Data JPA' 카테고리의 다른 글
querydsl 에서 case문 사용하기 (0) | 2024.01.07 |
---|---|
QueryDsl) BooleanExpression (1) | 2023.12.17 |
queryDsl 정리 및 예제 (1) | 2023.12.03 |
JPA) JPA Auditing으로 자동화 (0) | 2023.12.01 |
JPA) Entity Graph 로 N+1 이슈 해결하기 (0) | 2023.10.29 |