Main
Member member1 = new Member("member1",10,teamA);
Member member2 = new Member("member2",20,teamA);
Member member3 = new Member("member3",30,teamB);
Member member4 = new Member("member4",40,teamB);
Member member5 = new Member(null,100,teamB);
Member member6 = new Member("member6",100,teamB);
Member member7 = new Member("member7",100,teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
em.persist(member5);
em.persist(member6);
em.persist(member7);
🧩 조인
연관관계가 있는 필드로 조인
- join -> inner join을 기본으로 가져온다.
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.fetch();
System.out.println(result.toString());
- 결과
- 쿼리문
세타조인
- 연관관계가 없는 필드로 조인
- 회원의 이름이 팀 이름과 같은 회원 조회
em.persist(new Member("teamA"));
em.persist(new Member("teamB"));
List<Member> result2 = queryFactory
.select(member)
.from(member, team)
.where(member.username.eq(team.name))
.fetch();
System.out.println(result2.toString());
- 결과
- 쿼리문
회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회
List<Tuple> result3 = queryFactory
.select(member, team)
.from(member)
.leftjoin(member.team, team).on(team.name.eq("teamA"))
.join(member.team, team).on(team.name.eq("teamA"))
.fetch();
for(Tuple tuple : result3) {
System.out.println("tuple : " + tuple);
}
🧩 서브쿼리
- 나 자신을 가져다 쓸 때는 객체를 하나 더 만들어준다.
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
System.out.println("result : " + result.get(0).getAge());
List<Member> result2 = queryFactory
.selectFrom(member)
.where(member.age.in(
JPAExpressions.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
System.out.println("result2 : " + result2.get(0).getAge());
- 결과
- 쿼리
🧩 case 문
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);
}
- 결과
- 쿼리
🧩 상수, 문자 더하기
List<Tuple> result2 = queryFactory
.select(member.username, Expressions.constant("A"))
.from(member)
.fetch();
for(Tuple s: result2) {
System.out.println("Tuple : " + s);
}
List<String> result3 = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()))
.from(member)
.fetch();
System.out.println("Tuple : " + result3);
- 결과
- 쿼리
- Expressions.constant("A")) 여기는 쿼리문으로 나오지 않는다.
- concat결과
- 쿼리
🧩 결과 반환, 필드 & 생성자 접근, 별칭이 다를 때
- ExpressionUtils.as(source, alias) : 필드나, 서브쿼리에 별칭 적용
- 서브쿼리는 반드시
ExpressionUtils.as
를 사용
- username.as("memberName") : 필드에 별칭 적용
List<String> result = queryFactory
.select(member.username)
.from(member)
.fetch();
List<Tuple> result2 = queryFactory
.select(member.username,member.age)
.from(member)
.fetch();
jpql
List<MemberDTO> result3 = em.createQuery(
"select new com.koreait.querydsl.dto.MemberDTO(m.username, m.age)"
, MemberDTO.class)
.getResultList();
queryDSL
프로퍼티 접근 -> setter 접근 방법
- bean
- 첫번째 param : type지정(ex, MemberDTO.class)
- 두번쨰 param : 꺼내올 값 나열
- bean으로 접근하는 방식이기 떄문에 getter, setter 반드시 존재 해야한다.
List<MemberDTO> result4 = queryFactory
.select(Projections.bean(MemberDTO.class,
member.username,member.age))
.from(member)
.fetch();
필드 직접 접근
List<MemberDTO> result5 = queryFactory
.select(Projections.fields(MemberDTO.class,
member.username,member.age))
.from(member)
.fetch();
생성자 접근, 별칭이 다를 때
List<UserDTO> result6 = queryFactory
.select(Projections.fields(UserDTO.class,
member.username.as("name"),
member.age))
.from(member)
.fetch();
for(UserDTO userdto : result6) {
System.out.println("userDTO : " + userdto);
}
서브쿼리 별칭
- ExpressionUtils : 필드나, 서브쿼리 이름 줄 떄
- 나 자신에게 결과값을 준다. ->
QMember mSub = new QMember("mSub");
QMember mSub = new QMember("mSub");
List<UserDTO> result7 = queryFactory
.select(Projections.fields(UserDTO.class,
member.username.as("name"),
ExpressionUtils.as(
JPAExpressions
.select(mSub.age.max())
.from(mSub),"age")
))
.from(member)
.fetch();
for(UserDTO userdto : result7) {
System.out.println("userDTO : " + userdto);
}
- mSub 별칭이 다르면 값이 담기지 않지만
as
사용해서 alias
를 줘서 사용
🧩 동적 쿼리 - BooleanBuilder 사용
searchMember
메서드에 파라미터값을 넣어주는데, 파라미터 값이 있을 때, 없을 때가 있다.
- 이 조건을 넘겨 받아서
null
일 떄는 추가, null
이 아닐 때는 추가 해주지 않는다.
...
try{
...
em.flush();
em.clear();
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember(usernameParam, ageParam);
System.out.println("result.size() : " + result.size());
}
}
private static List<Member> searchMember(String usernameParam, Integer ageParam){
BooleanBuilder builder = new BooleanBuilder();
if(usernameParam != null) {
builder.and(member.username.eq(usernameParam));
}
if(ageParam != null) {
builder.and(member.age.eq(ageParam));
}
System.out.println("builder : " + builder.toString());
return queryFactory
.selectFrom(member)
.where(builder)
.fetch();
}
}
- 쿼리
- ?, ? 로 조건식이 2개 들어왔다
- usernameParam = null 로 바꾸면 age 1개만 들어온다
- 결과