20.03.29 16:56 작성
·
4.1K
0
영한님 안녕하세요.
JPQL 의 경우, From 절 내에서 SubQuery 를 지원하지 않으므로 Join 을 좀 더 활용하거나 또는 쿼리를 여러 개로 분해해서 첫번째 결과를 다음 쿼리의 파라미터에 넣어주는 방식으로 활용할 것을 권장해 주셨는데요.
혹시 From 절 내의 SubQuery 를 하나의 Query 로 뽑아낸 후, 결과 List 를 두번째 쿼리 안으로 집어 넣을 수도 있는 건가요? 다음 쿼리의 파라미터에 넣는다는 의미가 이러한 List 형태로 활용을 할 수 있는 것인지 좀 궁금합니다.
일부 강사님들 보면 보충이 필요하다고 생각되는 내용이 생기면 짧막하게 추가 영상도 넣어주시는 분들이 있던데 제 개인적으로는 From 절 내의 SubQuery 를 해결하는 예제를 하나 보여주시면 많은 분들에게 도움이 되지 않을까 생각이 듭니다. 실무에서 JPA 를 쓰기 전에 From 절 SubQuery 는 MyBatis 에서 워낙 많이 사용되던 용법이다보니 JPA 전환 과정에서 이 부분을 막연해 하는 개발자들을 많이 보이는 것 같습니다.
답변 4
1
2020. 03. 29. 22:43
안녕하세요. 아리마님 오랜만입니다^^
아직까지 해결되지 않은 JPA의 최대 걸림돌이 from절의 서브쿼리인 인라인뷰(inlineview) 이지요.
이 인라인뷰만 해결되면 정말 좋겠는데 ㅠㅠ 아호... hibernate6에서 내부 파서를 많이 업그레이드 하는 계획이 잡혀 있으니 한번 기대를 걸어보고 있습니다.
인라인뷰를 조인 방식으로 변경가능 하면 가장 좋겠지만, 사실 안되는 경우도 많습니다. 그래서 다음 3가지 방법을 순서대로 적용하는 고민이 필요합니다.
1. 조인으로 변경한다.
2. 쿼리를 여러개로 분리한다.
3. 그래도 답이 안나오면 네이티브 쿼리를 사용한다.
질문 주신 내용은 여기서 2번 쿼리를 여러개로 분리한다인데요. 사실 케이스가 너무 다양해서 딱 찝어서 말씀드리기는 쉽지 않은데, 제가 쿼리의 결과를 다음 쿼리의 파라미터에 넣는다는 의미를 간단하게라도 예제로 설명을 드렸어야 했겠다는 생각이 드네요. 고맙습니다^^
2번 방법은 단순히 하나의 쿼리를 둘, 셋으로 쪼개서 해결이 가능할 때도 있지만, 더 나아가서 애플리케이션의 도움을 충분히 받아서 문제를 해결하는 방식을 바꿔야 하는 경우도 있습니다. 하지만 복잡한 통계성 쿼리의 경우에는 네이티브 쿼리로 작성하는게 더 나은 경우도 많습니다.
좋은 예제는 아니지만, 2번의 쿼리 파라미터를 넣는다는 의미를 이해하실 수 있게 SQL 쿼리로 예시를 작성해보았습니다.
팀당 나이가 가장 많은 회원 이름과 그 나이를 구해라
MEMBER
ID | AGE | USERNAME | TEAM_ID |
---|---|---|---|
3 | 10 | member1 | 1 |
4 | 20 | member2 | 1 |
5 | 30 | member3 | 2 |
TEAM
ID | TEAM_NAME |
---|---|
1 | teamA |
2 | teamB |
쿼리 한번으로 해결(그런데 인라인뷰를 사용해야함)
select m.*
from member m, (select team_id, max(age) as max_age from member group by team_id) m2
where m.team_id = m2.team_id and m.age = m2.max_age;
결과
ID | AGE | USERNAME | TEAM_ID |
---|---|---|---|
4 | 20 | member2 | 1 |
5 | 30 | member3 | 2 |
쿼리 분리 시도(애플리케이션의 도움을 받아야함)
1. group 사용으로 사용자 이름, 사용자 id는 조회 불가능
select team_id, max(age) as max_age from member m2 group by team_id;
결과
TEAM_ID | MAX_AGE |
---|---|
1 | 20 |
2 | 30 |
2. 회원 추가 조회(1번 쿼리의 결과를 파라미터로 이용)
select m.team_id, m.username, m.age from member m
where (m.team_id = 1 and m.age = 20) or (m.team_id=2 and m.age=30);
결과
TEAM_ID | USERNAME | AGE |
---|---|---|
1 | member2 | 20 |
2 | member3 | 30 |
저도 JPA 사용하면서 인라인뷰 가끔 골치인데, 애매할 때는 차라리 네이티브 쿼리로 작성하시는 것을 권해드립니다.
예제에 추가로 넣어서 설명하는 부분은 한번 고민해보겠습니다^^!
감사합니다.
0
2020. 03. 30. 21:19
아리마님 잘 보시면 쿼리 결과가 하나의 Record가 아닙니다^^ List 형태로 반환된 상황입니다^^
물론 이렇게 어렵지만 풀어낼 수 있는 상황도 있고, 어쩔 수 없는 상황도 있습니다^^
0
2020. 03. 30. 01:05
항상 친절한 답변에 너무 감사드립니다.
그런데 영한님의 예시는 첫번째 쿼리 결과가 하나의 Record 일 때의 상황인데요.
문의드렸던 내용처럼 첫번째 쿼리 결과가 List 형태라면 파라미터로 활용하기는 불가능할 듯 한데
이런 경우는 어쩔 수 없이 Native Query 나 Mybatis 를 활용할 수 밖에 없는 거 겠죠?
2022. 08. 14. 15:57
philosophymeetsmath님 공유 감사합니다^^