TIL

TIL 221003 개인프로젝트 queryDsl 트러블슈팅

Vince_rf 2022. 10. 3. 17:58

# queryDsl 빌드 후 중복된 클래스 에러

queryDsl 그래들 빌드 후 어플리케이션 실행 시, 중복된 클래스가 존재한다는 에러이다.

 

구글링을 통해 발견한 해결법은 다음과 같다.

에러메세지를 읽어보고 위의 스크린샷과 같이 중복된 클래스가 생성된 것을 확인.
설정에서 빌드,실행,배포탭으로 들어간다
어노테이션 프로세서 탭에서 빨간색으로 동그라미친 부분들을 체크해주고 적용을 누르고 나온다.

 

물론 이 방법으로 해결한 케이스도 있겠지만.. 나의 경우에는 문제가 해결되지 않았다.

 

queryDsl 그래들 설정에 관한글을 이것저것 읽으며 설정 코드들을 여기저기서 가져온 것이 문제였는데..

buildscript {
    ext {
        queryDslVersion = "5.0.0"
    }
}

plugins {
    id 'org.springframework.boot' version '2.7.4'
    id 'io.spring.dependency-management' version '1.0.14.RELEASE'
    id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" // (1)
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-mustache'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
//querydsl 추가
    implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
    implementation "com.querydsl:querydsl-apt:${queryDslVersion}"

}

//querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"

querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}
sourceSets {
    main.java.srcDir querydslDir
}
compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}
//querydsl 추가 끝


tasks.named('test') {
    useJUnitPlatform()
}

이렇게 깔끔하게 정리해주니 정상작동했다.

 

나의 경우에는 맨 위에 있는 buildscript를 빼고 빌드를 진행하니 에러가 났었는데..

처음 의존성을 주입할 때, 안 그래도 dependencies에 ${queryDslVersion}이라는 환경변수는 대체 어디서 오는걸까? 라는 의문을 가지고 있었다.

 

이후에 

QuerydslConfig를 생성해주었고

@Configuration
@EnableJpaAuditing
public class QuerydslConfig {
    @PersistenceContext
    private EntityManager entityManager;

    public QuerydslConfig() {
    }

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(this.entityManager);
    }
}

 

단어 테이블인 Word에 @Table 어노테이션을 추가해주었다

@Table(name = "word")
@Entity
@Getter
@Setter
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class Word

그리고 커스텀할 인터페이스를 생성하고

public interface WordRepositoryCustom {

    List<Word> getWordList(String req);

    List<Word> getWordNameList(String req);

}

쿼리를 작성할 클래스를 생성하여 WordRepositoryCustom을 상속시켜 주었다.

@Repository
public class WordRepositoryImpl implements WordRepositoryCustom{
    private final JPAQueryFactory queryFactory;


    QWord word = QWord.word;

    public WordRepositoryImpl(JPAQueryFactory queryFactory) {
        this.queryFactory = queryFactory;
    }

    @Override
    public List<Word> getWordList(String req) {
        return queryFactory
                .selectFrom(word)
                .where(word.content.contains(req))
                .fetch();
    }

    @Override
    public List<Word> getWordNameList(String req) {
        return queryFactory
                .selectFrom(word)
                .where(word.name.contains(req))
                .fetch();
    }


}

쿼리를 작동시킬 매개변수가 String이므로, 서비스 단에서는 스트링 값을 매개변수로 넘겨주면 된다.

// 용어 뜻으로 용어 검색
    public List<WordResponseDto> searchByContent(WordRequestDto requestDto){
        List<Word> words = wordRepositoryCustom.getWordList(requestDto.getContent());
        List<WordResponseDto> responseDtos = new ArrayList<>();
        for (Word word : words){
            WordResponseDto wordResponseDto = new WordResponseDto(word);
            responseDtos.add(wordResponseDto);
        }
        return responseDtos;
    }

물론 컨트롤러 단에서 requestDto를 @RequestBody로 받아와야 한다.

// 용어 뜻으로 용어 검색
    @GetMapping("/api/search/content")
    public List<WordResponseDto> searchByContent(@RequestBody WordRequestDto requestDto){
        return wordService.searchByContent(requestDto);
    }

 

 

이 모든 과정이 내가 sql 쿼리를 선행학습하지 않았으면 불가능했을 것이다.

 

select나 where의 뜻을 알고있었기에 레퍼런스를 참고하면서 넘겨줄 매개변수나 저장할 데이터값을 쉽게 특정해낼 수 있었다. 역시 모든 지식은 이어져있다.

 

queryDsl을 사용해서 조인과 서브쿼리를 어떻게 사용하는지도 궁금해졌다.

 

계속 공부해서 더 깊은 지식을 쌓을 수 있도록 노력하자!

'TIL' 카테고리의 다른 글

TIL 221006 더 깊이 고민해보아야 할 문제들  (1) 2022.10.06
TIL 221004  (1) 2022.10.04
TIL 221001 개인프로젝트 SQL 쿼리  (0) 2022.10.01
220930 TIL 개인프로젝트 SQL쿼리 입문  (1) 2022.09.30
TIL 220929  (0) 2022.09.29