
"member1" 찾는 코드 작성
@Test
public void startJPQL() {
//member1 찾기
String qlString =
"select m from Member m " +
"where m.username=:username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
@Test
public void startQuerydsl() {
QMember m = new QMember("m");
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1")) //파라미터 바인딩 처리
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
QMember qMember = new QMember("m"); //별칭 지정
QMember qMember = QMember.member; //기본 인스턴스 사용
import static study.querydsl.entity.QMember.*;
@Test
public void startQuerydsl() {
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1")) //파라미터 바인딩 처리
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
member.username.eq("member1") //username = 'member1'
member.username.ne("member1") //username != 'member1'
member.username.eq("member1").not() //username != 'member1'
member.username.isNotNull() // 이름이 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) //age between (10, 30)
member.age.goe(30) //age >= 30
member.age.gt(30) //age > 30
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.startsWith("member") //like 'member%' 검색
/**
* JPQL
* select
* COUNT(m),
* SUM(m.age),
* AVG(m.age),
* MAX(m.age),
* MIN(m.age)
* from Member m
*/
@Test
public void aggregation() {
List<Tuple> result = queryFactory
.select(
member.count(),
member.age.sum(),
member.age.avg(),
member.age.max(),
member.age.min()
)
.from(member)
.fetch();
Tuple tuple = result.get(0);
assertThat(tuple.get(member.count())).isEqualTo(4);
assertThat(tuple.get(member.age.sum())).isEqualTo(100);
assertThat(tuple.get(member.age.avg())).isEqualTo(25);
assertThat(tuple.get(member.age.max())).isEqualTo(40);
assertThat(tuple.get(member.age.min())).isEqualTo(10);
}
/**
* 예) 회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회
* JPQL : select m,t from Member m left join m.team t on t.name = 'teamA'
*/
@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);
}
}
참고: on절을 활용해 내부조인을 하게 될 경우 where 절과 결과가 동일. 따라서 on절을 활용한 조인 대상 필터링을 사용할 때, 내부 조인이면 where 절을 사용하고, 외부 조인이 필요한 경우는 on절을 사용.
/**
* 연관관계가 없는 엔티티 외부 조인
* 회원의 이름이 팀 이름과 같은 대상을 외부 조인
*/
@Test
public void join_on_no_relation() throws Exception{
em.persist(new Member("teamA"));
em.persist(new Member("teamB"));
em.persist(new Member("teamC"));
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("tuple = " + tuple);
}
}
com.querydsl.jpa.JPAExpressions 사용
select 절에도 서브 쿼리 사용 가능
from 절의 서브 쿼리 한계
select, 조건절(where), order by에서 사용 가능
단순한 조건
@Test
public void basicCase() throws Exception{
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);
}
}
복잡한 조건
@Test
public void complexCase() throws Exception{
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();
for (String s : result) {
System.out.println("s = " + s);
}
}
order by 사용
/**
* 1. 0-30살이 아닌 회원을 가장 먼저 출력
* 2. 0-20살 회원 출력
* 3. 21-30살 회원 출력
* @throws Exception
*/
@Test
public void orderByCase() throws Exception{
NumberExpression<Integer> rankPath = new CaseBuilder()
.when(member.age.between(0, 20)).then(2)
.when(member.age.between(21, 30)).then(1)
.otherwise(3);
List<Tuple> result = queryFactory
.select(member.username, member.age, rankPath)
.from(member)
.orderBy(rankPath.desc())
.fetch();
for (Tuple tuple : result) {
String username = tuple.get(member.username);
Integer age = tuple.get(member.age);
Integer rank = tuple.get(rankPath);
System.out.println("username = " + username + " age = " + age + " rank = " + rank);
}
}
상수가 필요하면 Expressions.constant(xxx) 사용
@Test
public void constant() throws Exception{
List<Tuple> result = queryFactory
.select(member.username, Expressions.constant("A"))
.from(member)
.fetch();
for (Tuple tuple : result) {
System.out.println("tuple = " + tuple);
}
}
최적화가 가능하면 SQL에 constant 값을 넘기지 않는다. 상수를 더하는 것 처럼 최적화가 어려우면 SQL에 constant 값을 넘긴다.
문자 더하기 concat
@Test
public void concat() throws Exception{
//{username}_{age}
List<String> result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()))
.from(member)
.where(member.username.eq("member1"))
.fetch();
for (String s : result) {
System.out.println("s = " + s);
}
}
1빠요