첫 파라미터에 조인 대상을 지정 한 후, 두번째 파라미터에 별칭으로 사용할 Q 타입을 지정
join(조인 대상, 별칭으로 사용할 Q 타입)
기본 조인 사용 테스트
/**
* 팀 A 에 소속된 모든 회원
*/
@Test
public void join() throws Exception{
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");
}
세타 조인 테스트
/**
* 세타 조인(연관 관계가 없는 필드로 조인)
* 회원의 이름이 팀 이름과 같은 회원 조회
*/
@Test
public void theta_join() throws Exception{
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");
}
@Test
public void join_on_filtering() throws Exception{
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);
}
}
@Test
public void join_on_no_relation() throws Exception{
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);
}
}
하이버네이트 5.1 부터 on 을 사용해서 서로 관계가 없는 필드로 외부 조인하는 기능 추가 , 내부 조인도 가능하다.
문법의 경우 일반 조인과 다르게 leftjoin에 엔티티가 하나만 들어간다.
일반 조인 : .leftJoin(member.team, team)
on 조인 : from(member).leftJoin(team).on(member.username.eq(team.name))
추가로 참고한 내용 :페치조인(fetch Join )이란 :: 개발의 시작 (tistory.com)
@Test
public void fetchJoinUse() throws Exception{
em.flush();
em.close();
Member member1 = queryFactory
.selectFrom(member)
.join(member.team, team).fetchJoin()
.where(member.username.eq("member1"))
.fetchOne();
boolean loaded = emf.getPersistenceUnitUtil().isLoaded(member1.getTeam());
assertThat(loaded).as("페치 조인 적용").isTrue();
}
서브 쿼리란?
참고 사이트 : [DATABASE] 서브쿼리란? 서브쿼리 사용해보기 — 꽁담 (tistory.com)
/**
* 나이가 가장 많은 회원 조회.
*/
public void subQuery() throws Exception{
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
assertThat(result).extracting("age")
.containsExactly(40);
}
case 기본
@Test
public void basicCase(){
List<String> result = queryFactory
.select(member.age
.when(10).then("열살")
.when(20).then("스무살")
.otherwise("기타"))
.from(member)
.fetch();
for (String s : result) {
System.out.println("s = " + s);
}
}
복잡한 case 문
@Test
public void complexCase(){
List<String> result = queryFactory
.select(new CaseBuilder()
.when(member.age.between(0, 20)).then("0~20")
.when(member.age.between(21, 30)).then("20~30")
.otherwise("기타"))
.from(member)
.fetch();
for (String s : result) {
System.out.println("s = " + s);
}
}
Entity에서 선언되지 않은 필드 일때 상수 결과를 반호나하고 싶을 때 사용된다.
@Test
public void constant(){
List<Tuple> a = queryFactory
.select(member.username, Expressions.constant("A"))
.from(member)
.fetch();
for (Tuple tuple : a) {
System.out.println("tuple = " + tuple);
}
}
문자 더하기 Concat
@Test
public void concat(){
String result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()))
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
System.out.println(result);
}
member의 age의 경우 문자가 아니기 때문에 StringValue로 문자로 변환 가능