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
- apache.poi
- java
- ORM
- DevOps
- docker
- 자바8
- Jenkins
- MessageQueue
- spring
- rabbitmq
- 보안
- 엑셀 업로드
- jqGrid
- JPA
- Stream
- 그리드
- 제이쿼리그리드
- mom
- 자동빌드
- mssql
- stream api
- ci/cd
- 자동배포
- 대용량 업로드
- sqlserver
- QueryDSL
- poi
- JQuery
- 스트림
- Javascript
Archives
- Today
- Total
개발 메모장
[QueryDSL] QueryDSL 사용방법(2) 본문
728x90
#. 문자열 붙이기(Concat)
- 호출한 데이터들을 하나의 데이터로 연결하여 처리할 수 있는 기능입니다.
- concat 인스턴스는 String Expression으로 String 값을 인자로 받습니다.
- 따라서 String이 아닌 값에 대해선 StringValue()로 처리하여야 합니다.
- toString도 가능하나 객체 형태로 리턴합니다.
@GetMapping("concat")
public ResponseEntity<String> concatTest() {
String result = jpaQueryFactory.select(qMember.name.concat("-")
.concat(qMember.nickname)
.concat("-")
.concat(qMember.age.stringValue()))
.from(qMember)
.where(qMember.name.eq("드록바"))
.fetchOne();
return ResponseEntity.ok(result);
}


#. 상수 만들기
- 쿼리를 사용하다 보면 가끔 강제로 데이터를 주는 경우가 있을 것입니다.
- 이 경우 constant를 이용해 처리하면 됩니다.
- console에서 보는 쿼리에는 표기되지 않으나 결과를 보면 정상적으로 처리됐습니다.
@GetMapping("const")
public ResponseEntity<Tuple> constTest() {
Tuple tuple = jpaQueryFactory.select(qMember.nickname, Expressions.constant("캡틴"))
.from(qMember)
.fetchFirst();
return ResponseEntity.ok(tuple);
}


#. 서브쿼리
- 서브쿼리의 경우 JPAExpressions를 이용해 처리하면 됩니다.
- 동일 테이블로 서브쿼리를 만들어야 하는 경우 Q객체를 하나 더 만들어 처리하면 됩니다.
- 스칼라 서브쿼리를 사용한 데이터를 return 할 때에는 get 할 키값이 명확하지 않기에 아래와 같은 변수 생성 방식으로도 처리가 가능합니다.
@GetMapping("sub")
public ResponseEntity<List<Map<String, Object>>> subTest() {
// 서브쿼리
Expression<String> spAlias = JPAExpressions.select(qOrder.sp)
.from(qOrder)
.where(qOrder.name.eq("드록바"));
List<Tuple> result = jpaQueryFactory.select(qMember.name, qMember.email, spAlias)
.from(qMember)
.where(qMember.name.eq(JPAExpressions.select(qOrder.name)
.from(qOrder)
.where(qOrder.name.eq("드록바"))))
.fetch();
List<Map<String, Object>> resultLast = new ArrayList<>();
for(Tuple tuple: result) {
Map<String, Object> tupleMap = new HashMap<>();
tupleMap.put("name", tuple.get(qMember.name));
tupleMap.put("email", tuple.get(qMember.email));
tupleMap.put("sp", tuple.get(spAlias));
resultLast.add(tupleMap);
}
return ResponseEntity.ok(resultLast);
}

#. Case문
- 간단한 내용은 case ~ when ~ then으로 처리할 수 있지만 보통 그렇지 않을 것입니다.
- caseBuilder를 이용해 범위로 처리하는 방법입니다.
@GetMapping("case")
public ResponseEntity<List<Map<String, Object>>> caseTest() {
List<Tuple> result = jpaQueryFactory.select(new CaseBuilder().when(qMember.age.between(18, 22)).then("유망주")
.when(qMember.age.between(23, 31)).then("전성기")
.when(qMember.age.between(32, 40)).then("노장")
.when(qMember.age.between(41, 60)).then("은퇴")
.otherwise("X")
.as("asStatus"),
qMember.name,
qMember.age)
.from(qMember)
.fetch();
List<Map<String, Object>> resultListMap = new ArrayList<>();
for(Tuple tuple : result) {
Map<String, Object> map = new HashMap<>();
map.put("status", tuple.get(new CaseBuilder().when(qMember.age.between(18, 22)).then("유망주")
.when(qMember.age.between(23, 31)).then("전성기")
.when(qMember.age.between(32, 40)).then("노장")
.when(qMember.age.between(41, 60)).then("은퇴")
.otherwise("X")
.as("asStatus")));
map.put("name", tuple.get(qMember.name));
map.put("age", tuple.get(qMember.age));
resultListMap.add(map);
}
return ResponseEntity.ok(resultListMap);
}
#. distinct
- 쿼리에서 사용하는 것과 같이 동일하게 사용하면 됩니다.
@GetMapping("dist")
public ResponseEntity<List<Tuple>> dist(String name, Integer age) {
List<Tuple> result = jpaQueryFactory.select(qMember.name,
qMember.age).distinct()
.from(qMember)
.where(qMember.age.eq(34))
.fetch();
return ResponseEntity.ok(result);
}
#. 동적 쿼리
1. BooleanBuilder
- null 체크 후 BooleanBuilder를 통해 and로 해당 값을 이어주는 방식입니다.
- 전달받은 파라미터가 없을 경우 and를 하지 않아 전달한 파라미터에 대해서만 조건에 추가가 가능해집니다.
@GetMapping("dynamic")
public ResponseEntity<List<MemberEntity>> dynamic(String name, Integer age) {
BooleanBuilder builder = new BooleanBuilder();
if(name != null) {
builder.and(qMember.name.eq(name));
}
if(age != null) {
builder.and(qMember.age.eq(age));
}
List<MemberEntity> result = jpaQueryFactory.selectFrom(qMember)
.where(builder)
.fetch();
return ResponseEntity.ok(result);
}
- 파라미터 1개 입력 시 동작하는 쿼리

- 파라미터 2개 입력 시 동작하는 쿼리

- builder를 통해 알아서 처리가 가능합니다.
2. 메서드 이용
- 전달받은 파라미터를 이용해 booleanExpression을 통해 null인지 값이 있는지 체크하는 방법입니다.
// 아래의 메서드를 생성해주고
private BooleanExpression nameCheck(String name) {
return name != null ? qMember.name.eq(name) : null;
}
private BooleanExpression ageCheck(Integer age) {
return age != null ? qMember.age.eq(age) : null;
}
// where 인스턴스에 해당 메서드를 넣어 처리해줍니다.
List<MemberEntity> result = jpaQueryFactory.selectFrom(qMember)
.where(nameCheck(name)
, ageCheck(age))
.fetch();
#. update
- update도 마찬가지로 update ~ set ~ where ~ 와 같은 방식으로 처리합니다.
- 한 가지 다른 점은 마지막 인스턴스로 execute()를 사용하여 마무리합니다.
- 이때의 값은 업데이트 처리를 진행한 수를 반환합니다.
- 또한 상황에 따라 flush 및 clear 시켜줘야 문제없이 사용할 수 있으니 상황에 맞게 처리해 주시길 바랍니다.(@Transactional 사용 시 반드시 flush를 사용할 필요는 없으니 상황에 따라 처리해 주세요.)
(DB와 관련된 로직이 뒤에서 실행될 경우 clear 하게 되면 문제가 발생할 수 있습니다.)
@Transactional
@PutMapping("updatedsl")
public void update() {
long count = jpaQueryFactory.update(qMember)
.set(qMember.age, 28)
.where(qMember.name.eq("드록바"))
.execute();
em.flush();
// em.clear();
}


#. delete
- delete 또한 간편하게 처리가 가능합니다.
@Transactional
@DeleteMapping("deletedsl")
public void delete() {
long count = jpaQueryFactory.delete(qMember).where(qMember.name.eq("메시")).execute();
}

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
728x90
'ORM' 카테고리의 다른 글
[QueryDSL] QueryDSL Projection (0) | 2024.02.01 |
---|---|
[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 |