본문 바로가기
관리자

Programming-[Backend]/JPA

[Querydsl]2. 기본 문법

728x90
반응형

 

기본문법은 대부분 익숙한 내용이라, 몰랐던 부분이나 중요한 부분만 위주로 개조식으로 작성한다.

 

 

Q객체 생성하기

 

Maven으로 Build를 하면 Q 객체를 생성해줬었는데, Gradle은 Build를 해도 Q객체를 생성하지 않는다. 이전 글에서 배운 것처럼 compileQuerydsl을 직접해줘서 Q객체를 생성해줘야 한다. 

 

 

기본 문법

static import를 안해서 어색할 수 있다. Q객체의 alias를 "m"과 같이 설정하고, 해당 객체를 querydsl 문법으로 넘기는 방식을 적용함을 자각하고 있자. 이 alias는 querydsl이 JPQL을 작성할 때 sql문의 alias로 사용한다. 

 

같은 Q객체를 동시에 조회해야할 때, Q 객체의 alias를 지정해서 사용해주면 된다!

똑같은 엔티티에서 다른 내용을 조회해야할 때는 이 원리를 이용해야한다. 실무에서 이런 경우가 있었다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
  void startQuerydsl() throws Exception {
    /* GIVEN */
    JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(em);
    QMember m = new QMember("m");
 
    Member findMember = jpaQueryFactory
            .select(m)
            .from(m)
            .where(m.username.eq("member1"))
            .fetchOne();
 
    /* WHEN */
 
    /* THEN */
    assertThat(findMember.getUsername()).isEqualTo("member1");
 
  }
cs

 

일반적으로는 이렇게 alias를 사용하지 않고 Q객체에 미리 생성된 인스턴스를 사용한다. QMember.member로 작성하고, static import를 하면 된다.

 

 

JPAQueryFactory 선언

 

querydsl 문법을 사용할 수 있게 해주는 JPAQueryFactory를 선언해주어야 한다. 이 부분은 각 테스트 시마다 새로 생성되어야 하기 때문에, 테스트 클래스 전체에서 필드값으로 선언하고, entitymanager의 주입 및 생성은 @BeforeEach에서 진행되도록 해준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
 
  @Autowired
  EntityManager em;
 
  JPAQueryFactory jpaQueryFactory;
 
 
  @BeforeEach
  public void init() {
    /* GIVEN */
    jpaQueryFactory = new JPAQueryFactory(em);
 
...
 
cs

 

 


 

where절 검색 조건

 

참조용으로 강의자료를 저장해놓자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
member.username.eq("member1"// username = 'member1'
member.username.ne("member1"//username != 'member1'
member.username.eq("member1").not() // username != 'member1'
member.username.isNotNull() //이름이 is not null
member.age.in(1020// age in (10,20)
member.age.notIn(1020// age not in (10, 20)
member.age.between(10,30//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%’ 검색
...
cs

 

 


 

결과 조회

 

참조용으로 강의자료를 저장해놓자.

 

1
2
3
4
5
6
7
fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환
fetchOne() : 단 건 조회
  결과가 없으면 : null
  결과가 둘 이상이면 : com.querydsl.core.NonUniqueResultException
fetchFirst() : limit(1).fetchOne()
fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행
fetchCount() : count 쿼리로 변경해서 count 수 조회
cs

 

 

 


 

정렬

 

정렬에서 .nullsLast(), .nullsFirst() 메서드가 있다. 이것은 검색 결과에 null이 포함될 경우 null의 위치를 List의 앞이나 뒤로 설정해줄 수 있다.

 

 


조인

 

세타 조인

JPA의 세타조인은 querydsl에서 from 절에 조인하고자하는 엔티티들을 작성하면 된다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
  @DisplayName("세타조인 - 회원의 이름이 팀 이름과 같은 회원 조회")
  void theta_join() throws Exception {
  
    em.persist(new Member("teamA"));
    em.persist(new Member("teamB"));
 
    List<Member> result = jpaQueryFactory
            .select(member)
            .from(member, team)
            .where(member.username.eq(team.name))
            .fetch();
  }
cs

 

세타조인 : outer join과 on절

기본적으로 세타조인은 left outer join, right outer join이 불가한데, on 절을 사용하면 outer join이 가능하긴 하다. select 절에 원하는 엔티티들을 불러오고, on 절을 이용하여 left join을 실행하면 Team이 teamB라서 조건에 맞지 않는 null인 정보까지 불러와지는 것을 확인할 수 있다.

 

select절에 여러 객체(엔티티)를 불러오는 경우, 결과가 Tuple값으로 지정된다는 것도 알아두자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
  @DisplayName("회원과 팀을 조회하면서 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회")
  void join_on_filtering() throws Exception {
 
    List<Tuple> result = jpaQueryFactory
            .select(member, team)
            .from(member)
            .leftJoin(member.team, team).on(team.name.eq("teamA"))
            .fetch();
 
    for (Tuple tuple : result) {
      System.out.println("tuple = " + tuple);
    }
 
  }
cs

 


 

참조

 

1. 인프런_실전! Querydsl_김영한 님 강의

https://www.inflearn.com/course/Querydsl-%EC%8B%A4%EC%A0%84/dashboard

728x90
반응형