기본 Join 문법
조인의 기본 문법은 첫번째 파라미터에 조인 대상을 지정하고,
두번째 파라미터에 별칭(alias)으로 사용할 Q-Type을 지정하면 됩니다.
join(조인대상, 조인 대상 테이블(Q-Type Entity))
join()
, innerJoin()
: 내부 조인
leftJoin()
: left 외부 조인 (left outer join)
rightJoin()
: right 외부 조인 (right outer join)
JPQL의 On과 성능 최적화를 위한 fetch join
제공
Inner Join
Hibernate 5.1 부터 On을 사용해 서로 연관관계가 없는 필드로 외부조인 하는 기능이 추가되었습니다.
물론 내부 조인도 가능합니다.
주의할 점은 leftJoin() 부분에는 일반 조인과 다르게 엔티티 하나만 들어갑니다.
- 일반 조인 :
leftJoin(m.team, t)
- On 조인 :
from(member).leftJoin(team).on(xxx)
내부 조인은 join()
메서드를 사용하여 테이블 간의 관계를 설정하는 방식입니다.
아래의 코드에서 order.member
는 order
테이블과 member
테이블 사이의 관계를 나타냅니다.
join()
메서드의 첫 번째 인자로는 조인 대상 필드를, 두 번째 인자로는 조인할 대상 테이블을 전달합니다.
아래의 예제에서는 order.member
와 member
를 내부 조인하여 연결합니다.
val query = JPAQueryFactory(entityManager)
val order = QOrder.order
val member = QMember.member
val result = query
.select(order)
.from(order)
.join(order.member, member)
.fetch()
팀 A에 소속된 모든 회원을 조회하는 Inner Join 예시
/**
* 팀 A에 소속된 모든 회원 조인
* @desc Inner Join
*/
@Test
fun join() {
val m = QMember.member
val t = QTeam.team
val result = queryFactory
.selectFrom(m)
.join(m.team, t)
.where(t.name.eq("teamA"))
.fetch()
assertThat(result)
.extracting("name")
.containsExactly("member1", "member2")
}
회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회하는 예시
- JPQL :
SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'teamA'
- SQL :
SELECT m.*, t.* FROM Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name='teamA'
/**
* 회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회
* JPQL : SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'teamA'
* SQL : SELECT m.*, t.* FROM Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name='teamA' * @desc ON 절을 활용한 조인 (조인 대상 필터링)
*/
@Test
fun filterJoin() {
val m = QMember.member
val t = QTeam.team
val result = queryFactory
.select(m, t)
.from(m)
.leftJoin(m.team, t).on(t.name.eq("teamA"))
.fetch()
result.forEach { println("tuple = $it") }
결과값
t=[Member(id=3, username=member1, age=10), Team(id=1, name=teamA)]
t=[Member(id=4, username=member2, age=20), Team(id=1, name=teamA)]
t=[Member(id=5, username=member3, age=30), null]
t=[Member(id=6, username=member4, age=40), null]
Outer Join
외부 조인은 내부 조인과 유사하지만, join()
메서드 대신 leftJoin()
이나 rightJoin()
메서드를 사용하여 조인을 수행합니다.
외부 조인은 조인 대상이 되는 테이블의 데이터와 일치하지 않아도 결과에 포함됩니다.
leftJoin()
메서드는 왼쪽 테이블을 기준으로 조인을 수행하고,
rightJoin()
메서드는 오른쪽 테이블을 기준으로 조인을 수행합니다.
val result = query
.select(order)
.from(order)
.leftJoin(order.member, member)
.fetch()
Cross Join
크로스 조인은 각 테이블의 모든 조합을 생성하는 방식으로, 특정 조인 조건 없이 단순히 테이블 간의 모든 데이터 조합을 가져옵니다.
from()
메서드를 중복하여 사용하여 크로스 조인을 수행할 수 있습니다.
- 연관관계가 없는 필드로 조인
- from 절에 여러 엔티티를 선택해서 크로스 조인
- 외부 조인 불가능 ->
ON
을 사용하여 외부 조인 해결
/**
* 크로스 조인 (연관관계가 없는 필드로 조인)
* 회원의 이름이 팀 이름과 같은 회원 조회
* @desc Cross Join
*/
@Test
fun thetaJoin() {
val m = QMember.member
val t = QTeam.team
val result = queryFactory
.select(m)
.from(m, t)
.where(m.name.eq(t.name))
.fetch()
assertThat(result)
.extracting("name")
.containsExactly("teamA", "teamB")
}
'📦 Database > QueryDSL' 카테고리의 다른 글
간단한 조건 검색 (필터링, 상세검색) 기능 만들기 (Kotlin, QueryDSL) (1) | 2023.06.25 |
---|---|
Query Builder - SubQuery Join - eq & goe (0) | 2023.05.21 |
Query Builder - Aggregation & Group By & Having (0) | 2023.05.20 |
Query Builder - Sort, Paging (0) | 2023.05.20 |
Query Builder - 검색 조건 쿼리 (0) | 2023.05.20 |
열심히 살고 싶은 사람의 메모장
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!