일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- mysql
- spring
- K8s
- API
- bean
- Spring Data JPA
- offsetdatetime
- entity graph
- topic생성
- git
- consumer
- Kotlin
- QueryDSL
- Streams
- PAGING
- AWS
- Entity
- CI
- Kubernetes
- ECS
- mirror maker2
- JPA
- spring kafka
- Spring JPA
- CodePipeline
- transactionaleventlistener
- centos7
- kafka
- producer
- cd
- Today
- Total
Yebali
Join의 종류와 QueryDsl 본문
데이터 베이스는 다양한 테이블에 데이터를 나누어 담는다.
우리는 필요에 따라 각 테이블에 있는 데이터를 조합하여 하나의 데이터 셋으로 만들어야 하는 경우가 빈번히 있다.
Join의 종류와 해당 Join방법들을 QueryDsl을 이용해 구현하는 방법을 알아보자.
Entity
예시 Entity는 'Team'과 'Member'를 사용할 것이며, 1:N 관계이다.
@Entity
class Team (
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long,
val name: String,
@OneToMany(mappedBy = "team")
val members: MutableList<Member> = mutableListOf(),
)
@Entity
class Member(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long,
val name: String,
@ManyToOne
@JoinColumn(name = "team_id")
var team: Team?
)
Test data
테스트에 사용할 데이터는 아래와 같다.
Team은 team_A, team_B, team_C가 있다.
Member는 member_1~6이 있으며,
member_1, member_2는 Team_A에
member_3, member_4는 Team_B에 속하고
member_5, member_6은 Team에 속하지 않았다.
@BeforeEach
fun init() {
val teamA = Team.create("team_A")
val teamB = Team.create("team_B")
val teamC = Team.create("team_C")
teamRepository.save(teamA)
teamRepository.save(teamB)
teamRepository.save(teamC)
memberRepository.save(Member.create("member_1", teamA))
memberRepository.save(Member.create("member_2", teamA))
memberRepository.save(Member.create("member_3", teamB))
memberRepository.save(Member.create("member_4", teamB))
memberRepository.save(Member.create("member_5", null))
memberRepository.save(Member.create("member_6", null))
}
Inner Join
Inner Join은 교집합( A ∩ B ) 연산과 같다. 조인 키 값이 양쪽 테이블에 모두 존재하는 데이터만 결과 데이터로 나타난다.
QueryDsl을 이용한 inner join구현은 아래와 같다.
fun innerJoin(): MutableList<Member> {
return jpaQueryFactory.selectFrom(QMember.member)
.join(QMember.member.team, QTeam.team).fetchJoin()
.fetch()
}
실제 쿼리는 아래와 같이 나간다.
select
member0_.id as id1_0_0_,
team1_.id as id1_1_1_,
member0_.name as name2_0_0_,
member0_.team_id as team_id3_0_0_,
team1_.name as name2_1_1_
from
member member0_
inner join
team team1_
on member0_.team_id=team1_.id
조회된 결과는 아래와 같다.
member = member_1 / team = team_A
member = member_2 / team = team_A
member = member_3 / team = team_B
member = member_4 / team = team_B
Left Join
Left Join은 교집합 연산 결과와 차집합 연산 결과를 합친 것( (A ∩ B) ∪ (A - B) )과 같다.
조인 키 값이 양쪽에 공통적으로 존재하는 테이터와 왼쪽에 명시된 테이블에만 존재하는 데이터가 결과 데이터로 나타난다.
QueryDsl을 이용한 left join구현은 아래와 같다.
fun leftJoin(): MutableList<Member> {
return jpaQueryFactory.selectFrom(QMember.member)
.leftJoin(QMember.member.team, QTeam.team).fetchJoin()
.fetch()
}
실제 쿼리는 아래와 같이 나간다.
select
member0_.id as id1_0_0_,
team1_.id as id1_1_1_,
member0_.name as name2_0_0_,
member0_.team_id as team_id3_0_0_,
team1_.name as name2_1_1_
from
member member0_
left outer join
team team1_
on member0_.team_id=team1_.id
조회된 결과는 아래와 같다.
member = member_1 / team = team_A
member = member_2 / team = team_A
member = member_3 / team = team_B
member = member_4 / team = team_B
member = member_5 / team = null
member = member_6 / team = null
Right Join
Right join도 교집합 연산 결과와 차집합 연산 결과를 합친 것( (A ∩ B) ∪ (A - B) )과 같다. 단지 차집합의 기준이 Left join과 반대이다.
QueryDsl을 이용한 inner join구현은 아래와 같다.
fun rightJoin(): MutableList<Member> {
return jpaQueryFactory.selectFrom(QMember.member)
.rightJoin(QMember.member.team, QTeam.team).fetchJoin()
.fetch()
}
실제 쿼리는 아래와 같이 나간다.
select
member0_.id as id1_0_0_,
team1_.id as id1_1_1_,
member0_.name as name2_0_0_,
member0_.team_id as team_id3_0_0_,
team1_.name as name2_1_1_
from
member member0_
right outer join
team team1_
on member0_.team_id=team1_.id
조회된 결과는 아래와 같다.
member = member_1 / team = team_A
member = member_2 / team = team_A
member = member_3 / team = team_B
member = member_4 / team = team_B
member = null / team = null
member를 기준으로 right join을 했기 때문에 사실 inner join과 같게 나온다.
하지만 위의 Query를 직접 실행하면 아래와 같이 team_C까지 조회되는 것을 알 수 있다.
Outer Join
OUTER JOIN은 조인하는 여러 테이블에서 한쪽에는 데이터가 있고, 한 쪽에는 데이터가 없는 경우, 데이터가 있는 쪽 테이블의 내용을 모두 출력하는 것이다.
즉, 조건에 맞지 않아도 해당하는 행을 출력하고 싶을 때 사용한다.
'Spring' 카테고리의 다른 글
[Spring] 테스트에서 Static 메소드 Mocking하기 (0) | 2022.09.24 |
---|---|
Spring의 Filter와 Interceptor (0) | 2022.01.23 |
QueryDSL in Kotlin (0) | 2021.10.31 |
Spring JPA의 Cache (0) | 2021.10.31 |
Spring JPA에 기본 생성자가 필요한 이유 (0) | 2021.10.31 |