최근에 비슷한 유형의 일들만 하다보니 글을 쓸만한 주제가 없었는데, 마침 지금 개발하고있는 부분에서 QueryDsl의 서브쿼리를 사용할일이 생겨서 개발하면서 알게된 점들을 간략하게나마 정리해본다.
먼저 QueryDsl에서 서브쿼리는 인라인뷰(from절 서브쿼리)를 제외하고는 사용할 수 있도록 지원하고 있으며 개인적인 생각으로 from절 서브쿼리는 대부분의 경우에 join을 통해 해결할 수 있다고 생각하기 때문에 지원하지 않는다고해서 문제가 되지는 않는다고 생각한다.
QueryDsl의 의존성은 다음과 같이 추가해주면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
|
<dependency> <!-- QueryDsl JPA 라이브러리 -->
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<dependency> <!-- Q도메인 생성 라이브러리 -->
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
|
cs |
작업하면서 자바 ORM 표준 JPA 프로그래밍을 참고하고 공식문서들을 참조해서 코드를 작성했고, 책 내용과는 조금 다르게 코드를 작성했다. 대략 다음과 같이 코드들을 작성했다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
@Component // 책내용이나 정석은 인터페이스를 이용하여 Bean을 생성하는게 정석적인 방법임.
public class TestImpl extends QuerydslRepositorySupport {
public TestImpl() {
super(TestImpl .class);
}
/* 프로젝트 구조에 따라 추가가 필요한 경우가 있음(여러 개의 DB를 사용하는 경우)
@PersistenceContext(unitName = "naraeEmrPacsPlusPersistence")
@Override
public void setEntityManager(EntityManager entityManager) {
super.setEntityManager(entityManager);
}
*/
//QueryDsl을 사용할 메소드(인터페이스를 이용하는 경우 override메소드)
private void getData(long param1, String param2, String param3) {
// 책에서는 JPAQuery를 사용하는 것으로 설명되어 있는데,
// 나의 경우 select절 부터 사용할 것이기때문에 JPQLQueryFactory를 사용한다.
JPQLQueryFactory queryFactory = new JPAQueryFactory(getEntityManager());
BooleanBuilder booleanBuilder = new BooleanBuilder(); //조건절 생성을 위한 BooleanBuilder선언
QTest qtest = QTest.test; // Test모델의 qdomain 선언
QOther qother = QOther.other; //other모델의 qdomain
booleanBuilder.and(qtest.id.contains("1")); // 아이디에 1포함되는 경우 참
booleanBuilder.and(qtest.type.eq("test")); // 타입이 test인 경우 참
//where절 subQuery : qother의 id를 가져오는 서브쿼리를 qtest의 value조건에 추가
List<Test> result = queryFactory.select(qtest).from(qtest).where(booleanBuilder,
qtest.value.in(JPAExpressions.select(qother.id).from(qother))).fetch();
//select절 subQuery : 리턴값에 qtest의 개수를 가져오는 쿼리를 추가 + Expressions.as를 이용해 alias를 count로설정
List<TestDTO> result = queryFactory.select(Projections.constructor(TestDTO.class, qtest.id, qtest.type, qtest.value,
Expressions.as(JPAExpressions.selectFrom(qtest.count()),"count"))).from(qtest).where(booleanBuilder).fetch();
}
//TestDto 클래스
public class TestDTO {
private Long id;
private String type;
private String value;
private String count;
@QueryProjection
public TestDto(Long id, String type, Strin value, String count) {
this.id = id;
this.type = type;
this.value = value;
this.count = count;
}
}
}
|
cs |
QueryDsl에서 DTO사용에 관한건 이전에 작성했던 내용을 보면 될 것 같고,
Expressions.as는 alias를 추가해주는 기능으로 Expressions클래스내에선언되어있다. 외에 클래스 내에 template 메소드를 사용할 수도있는 것 같은데 나는 as메소드를 사용했다.
또 서브쿼리를 만들 수 있게해주는 JPAExpressions객체에는 select 외에 selectDistinct, selectZero등의 메소드도 있어서 상황에 따라 사용할 수 있을 것 같다.
'SPRING FRAMEWORK' 카테고리의 다른 글
CustomRepository의 PropertyReferenceException (0) | 2023.04.28 |
---|---|
jsp:include를 이용한 페이지 이동 (0) | 2022.02.24 |
@Transient 어노테이션 사용해보기 (0) | 2021.01.15 |
개발중 발생했던 @Autowired 관련 이슈 정리 (1) | 2021.01.07 |
Spring JPA에서 @Query를 사용하는 방법. (0) | 2020.09.22 |