250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바8
- rabbitmq
- java
- 보안
- JPA
- apache.poi
- stream api
- ORM
- 엑셀 업로드
- Jenkins
- 자동빌드
- Stream
- poi
- Javascript
- sqlserver
- 자동배포
- spring
- docker
- mssql
- 그리드
- MessageQueue
- ci/cd
- mom
- 스트림
- 대용량 업로드
- JQuery
- 제이쿼리그리드
- DevOps
- QueryDSL
- jqGrid
Archives
- Today
- Total
개발 메모장
[QueryDSL] QueryDSL Projection 본문
728x90
#. Projection이란?
- Projection은 테이블의 특정 컬럼만 조회할 수 있게 해주는 역할을 합니다.
- DB에서 필요한 데이터만 가져오기에 검색하는 데이터의 양을 줄이고 성능을 최적화하며 네트워크 오버헤드를 최소화하는데 도움이 됩니다.
#. Projection을 사용하는 이유
- 데이터 볼륨 최소화
- 전체 행이나 테이블을 가져오는 것이 아니라 필요한 정보만 검색할 수 있습니다.
- DB와 애플리케이션 간에 전송되는 데이터의 양을 줄이므로 대규모 데이터 세트를 처리할 때 유용합니다. - 성능 향상
- 필요한 열만 선택하면 쿼리의 전반적인 성능과 애플리케이션의 응답성을 향상시킬 수 있습니다.
- 불필요한 데이터 검색으로 인한 트래픽이 증가 및 쿼리 실행 시간이 지연을 방지할 수 있습니다. - 중복 방지
- 현재 쿼리와 관련이 없는 열을 제외하여 결과의 중복을 방지하는 데 도움이 됩니다.
- 이를 통해 애플리케이션의 특정 요구 사항에 맞게 출력을 맞춤화할 수 있습니다.
#. 왜 Projection을 사용해야 할까?
- q객체를 이용해 원하는 컬럼만 가져올 수 있지만 이 경우 리턴을 Tuple객체로 해야 합니다.
- Tuple 객체는 querydsl.core에서 사용하기 때문에 querydsl을 사용하지 않는 곳에서 데이터를 사용하려 하면 제대로 사용하기 어렵고 불편합니다.
- 따라서 projections를 통해 기존 DTO로 리턴 받을 수 있게 할 수 있습니다.
- 위처럼 여러 개의 컬럼을 조회하려 할 때 리턴형을 Tuple로 바꾸라고 오류가 발생합니다.
- 동일한 경우에 Projection을 사용하면 DTO객체 그 자체로 받을 수 있게 됩니다.
1. setter를 이용한 projection
- 위 사진과 같이 Projections.bean을 통해 DTO내 setter에 값을 채워줍니다.
- 장점 : setter를 이용하기에 생성자가 필요하지 않고 순서를 지키지 않아도 됩니다.
- 단점 : 불변성 보장이 어렵고 setter에 들어갈 값이 많아지면 가독성이 떨어집니다.
@GetMapping("proj")
public ResponseEntity<List<MemberEntity> > proj() {
List<MemberEntity> setterResult = jpaQueryFactory.select(Projections.bean(MemberEntity.class,
qMember.name,
qMember.age))
.from(qMember)
.where(qMember.age.eq(34))
.fetch();
return ResponseEntity.ok(setterResult);
}
2. fields를 이용한 projection
- 장점 : 불변성 유지가 가능합니다.
- 단점 : 기본생성자와 getter가 필요하며, 필드 순서를 동일하게 유지해야 합니다.
@GetMapping("proj")
public ResponseEntity<List<MemberEntity> > proj() {
List<MemberEntity> fieldResult = jpaQueryFactory.select(Projections.fields(MemberEntity.class,
qMember.name,
qMember.age))
.from(qMember)
.where(qMember.age.eq(34))
.fetch();
return ResponseEntity.ok(fieldResult);
}
3. constructor를 이용한 projection
- 생성자를 이용한 projection의 경우 select 내에 입력한 값들에 대한 생성자가 있어야 정상적으로 작동합니다.
- 아래 예제의 경우 name과 age를 사용하기 때문에 MemberEntity에 name, age 2개에 대한 생성자가 있다면 정상적으로 처리됩니다.
- 장점 : 불변성을 보장하고 생성자의 인자를 통해 필드를 쉽게 지정할 수 있습니다.
- 단점 : 순서를 정확히 맞춰야 합니다.
@GetMapping("proj")
public ResponseEntity<List<MemberEntity> > proj() {
List<MemberEntity> consturctorResult = jpaQueryFactory.select(Projections.constructor(MemberEntity.class,
qMember.name,
qMember.age))
.from(qMember)
.where(qMember.age.eq(34))
.fetch();
return ResponseEntity.ok(consturctorResult);
}
4. @QueryProjections를 이용한 projection
- 어노테이션을 사용하여 projection 하는 방법입니다.
- 어노테이션을 추가한 생성자는 q파일에 존재해야만 사용이 가능합니다.
- 따라서 어노테이션을 추가했다면 컴파일을 다시 해주시길 바랍니다.
- 장점 : 코드가 간결하고 불변성이 보장되며 순서 또한 상관없고 런타임에서 오류를 잡을 수 있습니다.
- 단점 : 생성자에 어노테이션을 붙이기에 지나친 QueryDSL 의존일 수 있습니다.
// MemeberEntity.java
@QueryProjection
public MemberEntity(String name, int age) {
this.name = name;
this.age = age;
}
// Controller
@GetMapping("proj")
public ResponseEntity<List<MemberEntity> > proj() {
List<MemberEntity> consturctorResult = jpaQueryFactory.select(new QMemberEntity(
qMember.name,qMember.age))
.from(qMember)
.where(qMember.age.eq(34))
.fetch();
return ResponseEntity.ok(consturctorResult);
}
#. 위와 같이 projection을 처리하는 4가지 방법에 대해 알아보았습니다.
#. 어떤 것을 사용해도 큰 문제는 없습니다만 각각의 장단점이 있는 만큼 상황에 따라 선택하여 사용하시길 바랍니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
728x90
'ORM' 카테고리의 다른 글
[QueryDSL] QueryDSL 사용방법(2) (1) | 2024.01.31 |
---|---|
[QueryDSL] QueryDSL 사용방법(1) (1) | 2024.01.30 |
[JPA] JPA의 정의와 사용 예제 (1) | 2024.01.10 |
[QueryDSL] QueryDSL 정의 및 설정방법 (0) | 2024.01.08 |
[myBatis] myBatis 사용방법 (1) | 2023.12.26 |