티스토리 뷰
이전 포스팅에서 한 테이블 내에서 특정 값을 그룹핑하여 최댓값을 가진 row를 가진 방법을 보았었다.
이때 Row_Number를 사용하여 추출한 데이터가 가장 빠른 방법으로 보였는데, 이는 서브 쿼리로 해야 한다는 점이 있다.
하지만..
JPQL?hibernate?에 의해 where절과 select절에서만 서브 쿼리가 사용 가능하다고 한다..(내부적인 원리는 나중에 따로 공부해봐야겠다.)
참고 글 : https://stackoverflow.com/questions/60258377/querydsl-4-x-subqueries-in-the-from-clause
ㅇㅏ무튼... 어떻게든 querydsl에서 서브 쿼리를 사용해서 위 케이스를 풀어낼 수 없을까 생각하다가.. 엔티티 레벨(?)에서 설정할 수 있는 법이 없을까 고민하다가 우연히 봤었던 @SubSelect 옵션이 생각났다.
참고 글 : https://stackoverflow.com/questions/25226244/what-is-the-use-of-synchronize-in-hibernate
마치 view처럼 사용할 수 있는 entity를 만드는 걸로 entity에 맵핑할 쿼리를 직접 작성하는 것이다.
/**
* Map an immutable and read-only entity to a given SQL select expression.
*
* @see Synchronize
*
* @author Sharath Reddy
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Subselect {
/**
* The query.
*/
String value();
}
주석의 내용과 같이 update될 수 없는 select용 엔티티이다.
@Entity
@Subselect(
"select " +
" ROW_NUMBER() over (PARTITION BY c.User_Seq ORDER BY Apply_Date desc, Config_Seq desc) as Row_Num, " +
" c.Config_Seq, " +
" c.User_Seq, " +
" c.Apply_Date " +
"from CONFIG c "
)
@Immutable
@Synchronize("CONFIG")
public class ConfigSubSelect {
@Column(name = "Row_Num")
private Long rowNum;
@Id
@GeneratedValue
@Column(name = "Config_Seq")
private Long configSeq;
@Column(name = "User_Seq")
private Long userSeq;
@Column(name = "Apply_Date")
private LocalDate applyDate;
}
이렇게 되면 테이블 단위가 아닌 subselect에 작성된 query로 결과가 엔티티에 맵핑되게 된다.
그리고 이 엔티티를 똑같이 querydsl에서 사용해보자.
query
.selectFrom(configSubSelect)
.where(configSubSelect.rowNum.eq(1L))
.fetch();
select configsubs0_.Config_Seq as config_s1_0_,
configsubs0_.Apply_Date as apply_da2_0_,
configsubs0_.Row_Num as row_num3_0_,
configsubs0_.User_Seq as user_seq4_0_
from (select ROW_NUMBER() over (PARTITION BY c.User_Seq ORDER BY Apply_Date desc, Config_Seq desc) as Row_Num,
c.Config_Seq,
c.User_Seq,
c.Apply_Date
from CONFIG c) configsubs0_
where configsubs0_.Row_Num = ?
실행결과의 query를 보면 서브 쿼리로 원하는 서브 쿼리가 나간 것을 확인할 수 있다.
querydsl은 jpql기반이기 때문에, JPQL 마찬가지로 동작될 것으로 예상되고, spring data jpa에서 제공하는 find~ 메서드 또한 동일하게 사용 가능하다.
물론, update나 insert는 불가능하고, 엔티티 파일을 하나 더 만들어야 하지만,
비즈니스적으로 서브 쿼리를 써야만 하는 테이블이라면 다른 곳에서도 똑같이 쓸 확률이 있기 때문에 만들어놓고 공통으로 사용해도 괜찮을 것 같다
'Web > JPA & QueryDSL' 카테고리의 다른 글
[JPA] 각각 다른 패키지에 클래스 이름이 같은 엔티티가 있을 경우 인식 문제 (30) | 2022.01.02 |
---|---|
[QueryDSL] IN 절에 여러개의 Parameter 사용하기 (30) | 2021.10.25 |
[QueryDSL & JPQL] Converter가 작동하지 않는 경우 (32) | 2021.09.20 |
- Total
- Today
- Yesterday
- IN Clause
- join subquery
- 로그인
- Animation
- 관리자 도구
- login
- oauth
- API
- playsinline
- playbackRate
- @EventListener
- Queue
- on('seek')
- 예제
- 장점
- QueryDSL
- @subquery
- 원리
- 특징
- 자바
- beforeunload
- @subselect
- jwplayer
- SET
- list
- SDK
- Multi IN Clause
- map
- 네트워크
- 의미
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |