Junjangsee's Blog

JPA - Common QueryDSL

2020-01-03

images

QueryDSL(Domain Specific Language)

JPA를 사용하다보면 메소드 이름을 통해 자동으로 쿼리를 생성했었습니다.

1
findByFirstNameIngoreCaseAndLastNameStartsWithIgnoreCase(String firstName, String lastName)

위와 같은 네임을 가지고 있다면 가독성이 너무 떨어질 뿐더러 쿼리가 추가될 때마다 여러 조건들이 추가될 것입니다.
하지만 QueryDSL을 사용하게 되면 타입세이프하게 쿼리를 만들어 사용할 수 있습니다.

홈페이지 : querydsl


연동 방법

기본 리포지토리 커스터마이징 안 했을 때

querydsl 먼저 Account 엔티티와 JpaRepository를 상속받는 Repository를 생성합니다.

querydsl 그리고 빈 주입 테스트를 하기 위해 테스트를 실행합니다.
여기서 이상이 없다면 성공하게 됩니다! 이제 의존성플러그인을 추가해보겠습니다.

의존성 추가

1
2
3
4
5
6
7
8
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>

querydsl 의존성을 추가해줍니다. QueryDSL은 스프링 부트가 의존성을 관리해주므로 버전을 명시하지 않아도 됩니다.
apt모듈은 QueryDSL이 Entity모델을 보고 Query용 Specific Language(특정 언어)를 만들어 주는 모듈입니다.

플러그인 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>

querydsl 빌드하면 target/generated-sources/java에 클래스를 생성하겠며, JPA를 사용하겠다는 의미입니다.
레퍼런스참고

querydsl 위와 같이 의존성을 다 추가한 다음 Maven - Lifecycle - compile 클릭해서 빌드하게 되면

querydsl 빌드 성공시 플러그인에 선언했던 경로에 생성된 것을 볼 수 있습니다.

생성된 클래스가 자동완성이 안된다면?

여기에 생성된 QAccount 클래스가 만약 자동완성이 안되는 경우가 생긴다면 어떻게 해야할까요?
querydsl Project Structure에 들어가 해당 경로를 Sources로 바꾸어주면 해결됩니다.

1
2
public interface AccountRepository extends JpaRepository<Account, Long>, QuerydslPredicateExecutor<Account> {
}

querydsl Repository에 QuerydslPredicateExecutor<T>를 상속받습니다. 타입에는 엔티티를 넣어주면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.querydsl.core.types.Predicate;

@RunWith(SpringRunner.class)
@DataJpaTest
public class AccountRepositoryTest {

@Autowired
AccountRepository accountRepository;

@Test
public void crud() {
Predicate predicate = QAccount.account
.firstName.containsIgnoreCase("junjang")
.and(QAccount.account.lastName.startsWith("kim"));

Optional<Account> one = accountRepository.findOne(predicate);
assertThat(one).isEmpty();
}
}

querydsl querydsl predicate를 생성하여 생성된 QAccount 객체로 쿼리를 작성하여 테스트 합니다.


기본 리포지토리 커스터마이징 했을 때

기본 구현 리포지토리가 아닌 커스텀한 리포지토리 구현체에 QuerydslPredicateExecutor<T>를 상속받고 생성자를 생성해주면 됩니다.