QueryDSL for Spring Data JPA
Github: https://github.com/syakuis/spring-data-jpa-querydsl
Gradle의 annotationProcessor로 심플하게 설정 방법이 줄어들었다. 더 이상 플러그인은 사용하지 않아도 된다. 참고: https://iammert.medium.com/annotation-processing-dont-repeat-yourself-generate-your-code-8425e60c6657
Gradle 버전은 6.5 이며 스프링 부트 버전은 2.4.5 이다.
ext.querydslVersion = "4.4.0"
def querydslDir = "${buildDir}/generated/querydsl"
sourceSets {
main.java.srcDir querydslDir
}
dependencies {
implementation "com.querydsl:querydsl-jpa:${querydslVersion}"
annotationProcessor(
"jakarta.persistence:jakarta.persistence-api",
"jakarta.annotation:jakarta.annotation-api",
"com.querydsl:querydsl-apt:${querydslVersion}:jpa"
)
}
스프링 빈 설정
@Configuration
public class QuerydslConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
QuerydslRepositorySupport 사용하여 구현하기
QueryDSL에서 제공하는 클래스를 상속하여 사용할 수 있다.
@Repository
public class SignupAccountRepository extends QuerydslRepositorySupport {
private final JPAQueryFactory jpaQueryFactory;
public SignupAccountRepository(JPAQueryFactory jpaQueryFactory) {
super(AccountEntity.class);
this.jpaQueryFactory = jpaQueryFactory;
}
public boolean existsByUsername(String username) {
return jpaQueryFactory.selectFrom(accountEntity)
.where(accountEntity.deleted.isNotNull().and(accountEntity.username.eq(username))).limit(1).fetchCount() > 0;
}
}
@DataJpaTest는 QuerydslConfiguration 을 로드하지 못하므로 @SpringBootTest 를 선언하여 테스트를 작성해야한다.
Spring Data JPA 와 함께 사용하기
QuerydslRepositorySupport를 사용하면 두개의 Repository 를 관리해야하며 @DataJpaTest 를 사용할 수 없다 하지만 Spring Data JPA와 함께 사용하면 하나의 Repository와 @DataJpaTest를 사용할 수 있게 된다.
QueryDSL 전용 인터페이스와 구현 클래스를 작성해야 한다. 인터페이스 ~Custom, 구현 클래스는 ~Impl 의 접미사를 클래스명으로 사용해야한다.
QueryDSL Interface & Class
public interface AccountRepositoryCustom {
boolean existsByUsername(String username);
}
@RequiredArgsConstructor
public class AccountRepositoryImpl implements AccountRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
@Override
public boolean existsByUsername(String username) {
return jpaQueryFactory.selectFrom(accountEntity)
.where(accountEntity.deleted.isNotNull().and(accountEntity.username.eq(username))).limit(1).fetchCount() > 0;
}
}
Spring Data JPA Repository
public interface AccountRepository extends JpaRepository<AccountEntity, Long>, AccountRepositoryCustom {
Optional<AccountEntity> findByUsername(String username);
}
Test Code
@ExtendWith(SpringExtension.class)
@DataJpaTest
@Import(QuerydslConfiguration.class)
class AccountRepositoryTest {
@Autowired
private AccountRepository accountRepository;
@Test
void existsByUsername() {
accountRepository.deleteById(accountEntity.getId());
assertTrue(accountRepository.existsByUsername("test"));
assertFalse(accountRepository.existsByUsername("I51in"));
}
}
Annotation을 만들어 사용할 수 있다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@DataJpaTest
@Import(QuerydslConfiguration.class)
public @interface QuerydslTest {
}
'Tech' 카테고리의 다른 글
OpenFegin Example (0) | 2021.10.07 |
---|---|
Java Database Connection TLS 보안 이슈 (0) | 2021.10.07 |
Spring RestDocs 작성 가이드 #2 응용편 - 보일러플레이트 코드 제거 (0) | 2021.09.14 |
Spring RestDocs 작성 가이드 #1 기본편 (0) | 2021.09.14 |