use_sql_comments: true
추가시 Querydls이 어떻게 JPQL로 바뀌는지 주석으로 확인 가능
검색 조건 쿼리
member.username.eq("member1") // username = 'member1'
member.username.ne("member1") // username != 'member1'
member.username.isNotNull() // 이름이 is not null
member.age.in(10, 20) // age in (10, 20)
member.age.notIn(10, 20) // age not in (10, 20)
member.age.between(10, 30) // between 10, 30
member.age.goe(30) // age >= 30(greater or equal)
member.age.gt(30) // age > 30(greater than)
member.age.loe(30) // age <= 30
member.age.lt(30) // age < 30
member.username.like("member%") // like 검색
member.username.contains("member") // like '%member%' 검색
member.username.startWith("member") // like 'member%' 검색
@Test
public void searchAndParam(){
Member findMember = queryFactory
.selectFrom(member)
.where(
member.username.eq("member1"),
member.age.eq(10)
)
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
and Param는 ,(콤마)를 사용해서 생략가능 -> 동적쿼리시 위력발휘
결과 조회
fetch(): 리스트 조회, 데이터 없으면 빈 리스트
fetchOne(): 단건 조회, 없으면 null 둘이상이면 Exception
fetchFrist(): limit(1).fetchOne()
fetchResults(): 페이징 정보 포함, total count 쿼리 추가 실행 (참고: 복잡한 쿼리를 최적화 할때는 비권장)
QueryResults<Member> results = queryFactory
.selectFrom(member)
.fetchResults();
results.getTotal();
List<Member> content = results.getResults();
fetchCount(): count 쿼리로 변경해서 count 수 조회
select count(m) from Member m -> JPQL에 엔티티를 직접 지정하면 아이디 즉 count(m.id)로 바뀜
정렬
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(100))
.orderBy(member.age.desc(), member.username.asc().nullsLast())
.fetch();
1. 나이 내림차순 2. 이름 오름차순 3. 이름없으면 맨뒤로
페이징
List<Member> result = queryFactory
.selectFrom(member)
.orderBy(member.username.desc())
.offset(1)
.limit(2)
.fetch();
집합
List<Tuple> result = queryFactory
.select(
member.count(),
member.age.sum(),
member.age.avg(),
member.age.max(),
member.age.min()
)
.from(member)
.fetch();
튜플을 쓰는이유: 지금은 셀렉트 데이터 타입이 여러개이기 때문임
그룹핑
List<Tuple> result = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.fetch();
having: 걸러
.groupBy(item.price)
.having(item.price.gt(1000))
조인
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("teamA"))
.fetch();
테이블간 연관관계가 있어야만 조인되는것은 아니다.
세타조인: 무지성 막조인(연관관계 없는 필드 끼리도 가능)
List<Member> result = queryFactory
.select(member)
.from(member, team)
.where(member.username.eq(team.name))
.fetch();
테이블이 곱하기 됨
페치 조인(쿼리 한방에 데이터 몽땅 가져오기): 주로 N+1 문제 해결
Member findMember = queryFactory
.selectFrom(member)
.join(member.team, team).fetchJoin()
.where(member.username.eq("member1"))
.fetchOne();
fetchJoin()만 추가
조인 ON 절
1. 필터링 용도
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(member.team, team)
.on(team.name.eq("teamA"))
.fetch();
멤버는 다 조회하면서 팀 이름이 teamA인것만 가져오고 나머지는 null
-> where는 팀 이름이 teamA인 멤버만 가져옴 (inner join일 경우는 on절과 where절이 똑같음)
2. 연관관계 없는 필드 조인
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(team).on(member.username.eq(team.name))
.fetch();
(주의) 위에 leftJoin(member.team, team) 과 달리 leftJoin(team)에 on절 사용
세타조인과 달리 on절을 사용해서 멤버테이블을 살리면서 left join가능
서브 쿼리: 쿼리 안에 쿼리
where절에 서브쿼리
QMember memberSub = new QMember("memberSub"); // 충돌 일어나지 않게 서브쿼리 별칭 구분해줘야함
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.in(
JPAExpressions
.select(memberSub.age)
.from(memberSub)
.where(memberSub.age.gt(10))
))
.fetch();
select절에 서브쿼리
QMember memberSub = new QMember("memberSub");
List<Tuple> result = queryFactory
.select(member.username,
JPAExpressions
.select(memberSub.age.avg())
.from(memberSub))
.from(member)
.fetch();
한계: from절에선 서브쿼리 못씀
해결방법
1.서브쿼리를 join으로 변경
2.애플리케이션에서 쿼리 두번 나눠서 실행
3.nativeSQL 사용
Case 문
List<String> result = queryFactory
.select(member.age
.when(10).then("열살")
.when(20).then("스무살")
.otherwise("기타"))
.from(member)
.fetch();
복잡할때: CaseBuilder 사용
List<String> result = queryFactory
.select(new CaseBuilder()
.when(member.age.between(0, 20)).then("0~20살")
.when(member.age.between(21, 30)).then("21~30살")
.otherwise("기타"))
.from(member)
.fetch();
왠만해서는 디비는 최소한의 필터링과 그룹핑만 하도록 해야함 -> 애플리케이션에서 처리하도록 함
상수,문자 더하기
List<Tuple> result = queryFactory
.select(member.username, Expressions.constant("A")) // 그냥 문자 A 이름옆에 추가
.from(member)
.fetch();
문자 붙이기
//username_age
List<String> result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue())) // int -> String 형변환 주의
.from(member)
.where(member.username.eq("member1"))
.fetch();
'웹 프로그래밍 > JPA' 카테고리의 다른 글
연관관계 편의 메서드 (0) | 2024.01.15 |
---|---|
Querydsl 중급 (0) | 2023.03.22 |
스프링 데이터 JPA (0) | 2023.03.18 |
JPA 활용(2) 팁 정리 (0) | 2023.03.16 |
JPA 활용(1) 팁 정리 (0) | 2023.03.08 |