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 | 31 |
Tags
- JPQL
- BOJ
- 다대일
- 즉시로딩
- dfs
- 낙관적락
- 동적sql
- 일대다
- eager
- 연결리스트
- PS
- 백트래킹
- 유니크제약조건
- 데코레이터
- SQL프로그래밍
- querydsl
- 지연로딩
- shared lock
- 다대다
- exclusive lock
- 힙
- CHECK OPTION
- 스토어드 프로시저
- execute
- 연관관계
- fetch
- 이진탐색
- 비관적락
- FetchType
- 스프링 폼
Archives
- Today
- Total
흰 스타렉스에서 내가 내리지
[Querydsl] 조인 본문
728x90
join(조인 대상, 별칭으로 사용할 Q타입)
# 기본 조인
/**
* 팀 A에 소속된 모든 회원
*/
@Test
public void join(){
QMember member = QMember.member;
QTeam team = QTeam.team;
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("teamA"))
.fetch();
assertThat(result)
.extracting("username")
.containsExactly("member1", "member2");
}
- join(), innerJoin() : 내부 조인 (inner join)
- leftJoin() : left 외부 조인 (left outer join)
- rightJoin() : right 외부 조인 (right outer join)
- JPQL 의 on 과 성능 최적화를 위한 fetch 조인 제공 → 나중에
# 세타 조인 - 연관관계가 없는 필드끼리 조인
/**
* 세타 조인 (연관관계가 없는 필드로 조인)
* 회원의 이름이 팀 이름과 같은 회원 조회
*/
@Test
public void theta_join(){
em.persist(new Member("teamA"));
em.persist(new Member("teamB"));
List<Member> result = queryFactory
.select(member)
.from(member, team)
.where(member.username.eq(team.name))
.fetch();
assertThat(result)
.extracting("username")
.containsExactly("teamA", "teamB");
}
- from 절에 여러 엔티티를 선택해서 세타 조인
- 외부 조인 불가능 → 다음에 설명할 조인 on 을 사용하면 외부 조인 가능
# 조인 - on 절
1. 조인 대상 필터링
/**
* 예) 회원과 팀을 조인하면서, 팀 이름이 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'
*/
@Test
public void join_on_filtering(){
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(member.team, team).on(team.name.eq("teamA"))
.fetch();
for (Tuple tuple : result){
System.out.println("tuple = " + tuple);
}
}
결과
tuple = [Member(id=1, username=member1, age=10), Team(id=1, name=teamA)]
tuple = [Member(id=2, username=member2, age=20), Team(id=1, name=teamA)]
tuple = [Member(id=3, username=member3, age=30), null]
tuple = [Member(id=4, username=member4, age=40), null]
2. 연관관계 없는 엔티티 외부 조인
/**
* 예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
* JPQL : SELECT m, t FROM Member m LEFT JOIN Team t on m.username = t.name
* SQL : SELECT m.*, t.* FROM Member m LEFT JOIN Team t ON m.username = t.name
*/
@Test
public void join_on_no_relation(){
em.persist(new Member("teamA"));
em.persist(new Member("teamB"));
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(team).on(member.username.eq(team.name))
.fetch();
for (Tuple tuple : result){
System.out.println("t = " + tuple);
}
}
- Hibernate 5.1 부터 on 을 사용해서 서로 관게가 없는 필드로 외부 조인하는 기능이 추가되었다.
- leftJoin() 부분에 일반 조인과 다르게 엔티티 하나만 들어간다
- 일반조인 : leftJoin(member.team, team)
- on조인 : from(member).leftJoin(team).on(xxx)
결과
t = [Member(id=1, username=member1, age=10), null]
t = [Member(id=2, username=member2, age=20), null]
t = [Member(id=3, username=member3, age=30), null]
t = [Member(id=4, username=member4, age=40), null]
t = [Member(id=5, username=teamA, age=0), Team(id=1, name=teamA)]
t = [Member(id=6, username=teamB, age=0), Team(id=2, name=teamB)]
# 페치 조인
@PersistenceUnit
EntityManagerFactory emf;
/**
* 페치 조인 적용
* 즉시로딩으로 Member, Team SQL 쿼리 조인으로 한 번에 조회
*/
@Test
public void fetchJoinUse(){
em.flush();
em.clear();
Member findMember = queryFactory
.selectFrom(member)
.join(member.team, team).fetchJoin()
.where(member.username.eq("member1"))
.fetchOne();
boolean loaded = emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam());
assertThat(loaded).as("페치 조인 미적용").isTrue();
}
- join(), leftJoin() 등 조인 기능 뒤에 fetchJoin() 이라고 추가하면 된다.
'JPA' 카테고리의 다른 글
[Querydsl] 프로젝션 결과 반환 - DTO 조회 (0) | 2024.04.19 |
---|---|
[Querydsl] 서브쿼리 (0) | 2024.04.19 |
[Querydsl] 집합 함수, GroupBy (0) | 2024.04.18 |
[Querydsl] 정렬과 페이징 (0) | 2024.04.18 |
[Querydsl] 결과 조회 (0) | 2024.04.18 |