<JPAQuery>
SELECT
G.group_name
I.gender,
COUNT(I.idol_id)
FROM tbl_idol I
join tbl_group G
GROUP BY I.gender, G.group_id
HAVING COUNT(I.idol_id) <= 3;
이런 쿼리 문을 JPA로 만들게 되면
List<Tuple> list = factory
.select(idol.group, idol.gender, idol.count())
.from(idol)
.groupBy(idol.gender, idol.group)
.having(idol.count().loe(3))
.fetch();
// then
for (Tuple tuple : list) {
Group group = tuple.get(idol.group);
String gender = tuple.get(idol.gender);
Long count = tuple.get(idol.count());
위와 같은 식으로 Tuple로 받아서 쓸수있다.
새부 적으로 보면 selelct는 사실상 그대로 쓰는데 ()안에 기입해야 하면 from도 같고 다 같다. 그러나 having절이 조금 어렵기때문에 추가적인 공부가 불가피해 보인다. 또한 마지막에 fetch를 붙여야 작동함을 알수있다. 그리고 Tuple 방식으로 받기 때문에 iter문법을 사용하여 가져오는 것으로 해야한다.
<subQuery>
SELECT G.group_name, AVG(I.age)
FROM tbl_idol I
JOIN tbl_group G
ON I.group_id = G.group_id
GROUP BY G.group_id
HAVING AVG(I.age) BETWEEN 20 AND 25
위와 같은 JOIN이 포함된 쿼리문은 아래와 같이 작성할수있다.
List<Idol> result = factory
.select(idol)
.from(idol)
.where(idol.age.gt(
JPAExpressions
.select(idol.age.avg())
.from(idol)
.where(idol.group.groupName.eq(groupName))
))
.fetch();
내부 로직에서 JPAExpressions를 이용하여 query도 중첩구문처럼 사용이 가능한것으로 이해하였다.
세부적으로 보면 다 같으나 where절에 JPAExpressions을 이용하여 다시 select문부터 중첩적으로 사용하는 것을 볼수있따. 안에 있는것이 innerjoin의 값임을 알수있다. 따라서 JPAExtenstion에 어떤것이 들어갈수있고 들어갈지 충분히 헷갈릴수있으므로 차분하게 볼필요가 있다.
for (GroupAverageAgeDto dto : result) {
String groupName = dto.getGroupName();
Double averageAge = dto.getAverageAge();
또한 Tuple 형식으로 정보가 오기 때문에 위와 같이 iter문을 이용하여 해석해서 확인할수있다.
위와 같은 형식을 편하게 쓰기위해서 SQL 공부를 게을리하지 않아야 할듯하다.
<동적Query>
@Test
@DisplayName("")
void dynamicTest1 () {
// given
String name = "null";// -> 값이 전달되지 않았다고 가정하자.
String gender = "null";
//동적 쿼리를 위한 BooleanBuilder
BooleanBuilder booleanBuilder = new BooleanBuilder();
if (name!=null) {
booleanBuilder.and(idol.idolName.eq(name));
}
if (gender!=null) {
booleanBuilder.and(idol.gender.eq(gender));
}
// when
List<Idol> result = factory
.select(QIdol.idol)
.where(booleanBuilder)
.fetch();
// then
result.forEach(System.out::println);
}
위와 같이 JPA 쿼리문을 사용하게 되면 동적 쿼리라고 한다. 이렇게 사용하게 되면 값이 어떤것이 null일지라도 다른 방식으로 실행하도록 유도한다.
다시말해 함수를 포함시키는 개념인듯하다.
@Test
@DisplayName("")
void dynamivTest2() {
// given
String name = "null";// -> 값이 전달되지 않았다고 가정하자.
String gender = "null";
// when
List<Idol> result = factory
.select(QIdol.idol)
.where(nameEq(name), genderEq(gender))
.fetch();
result.forEach(System.out::println);
}
private BooleanExpression nameEq(String nameParam) {
return nameParam != null ? idol.idolName.eq(nameParam) : null;
}
private BooleanExpression genderEq(String genderParam) {
return genderParam != null ? idol.gender.eq(genderParam) : null;
}
위방식도 동적JPA인데 전에 방식을 더 자세하게 쓰인다고 볼수있다.
BooleanExpression nameEq와 BooleanExpression nameEq의 함수를 보면 null이나오게 유도하는 것은 쿼리문을 없애고 실행하여 오류를 제거하기 위함이고 각각 파라미터값이 들어오면 정상적으로 실행되도록 하게됩니다,
@Test
@DisplayName("동적 정렬을 사용한 아이돌 조회")
void dynamicTest3() {
// given
String sortBy ="idolName" // 나이, 이름, 그룹명
boolean asc = true; // 오름차 true, 내림차 false
OrderSpecifier<?> specifier = null;
//동적 정렬 조건 생성
switch (sortBy){
case "idolName":
specifier = asc ? idol.idolName.asc() : idol.idolName.desc();
break;
case "gender":
specifier = asc ? idol.gender.asc() : idol.gender.desc();
case "age":
specifier = asc ? idol.age.asc() : idol.age.desc();
}
// when
factory
.select(idol)
.orderBy(specifier)
.fetch();
// then
}
위와 같은 식으로 응용이 가능하다. ㄹㅇ JAVA는 무궁무진한 방법으로 표현이 가능한것 같다.
++추가++

스프링 초기 설정입니다!!!
'PlayData 백엔드 부트캠프 정리' 카테고리의 다른 글
| 다시 시작하는 부트 캠프 하루 후기 9일차 (0) | 2024.11.06 |
|---|---|
| 다시 시작하는 부트 캠프 하루 후기 7일차 (0) | 2024.11.05 |
| 다시 시작하는 부트 캠프 하루 후기 5일차 (1) | 2024.10.18 |
| 다시 시작하는 부트 캠프 하루 후기 4일차 (1) | 2024.10.18 |
| 다시 시작하는 부트 캠프 하루 후기 3일차 (0) | 2024.10.16 |