Springboot

[Springboot] QueryDSL

KJihun 2023. 8. 8. 23:00
728x90

 

물물교환 프로젝트 진행 간 경매 시스템을 추가하기로 했다.

찾아보니 경매에서는 하한가가 필요했다.

하한가 설정을 위해 팀원끼리 많이 고민했으나 우선은 등록한 물건의 가격을 랜덤한 유저가 적절하다고 판단하는 값을

입력하게 하여 평균값을 산출 후 하한가로 적용하기로 했다.

 

gradle.build

dependencies {
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}
...

def querydslSrcDir = 'src/main/generated'
clean {
    delete file(querydslSrcDir)
}
tasks.withType(JavaCompile) {
    options.generatedSourceOutputDirectory = file(querydslSrcDir)
}

 

 

QuerydslConfig

@Configuration
public class QuerydslConfig {

    @Bean
    JPAQueryFactory jpaQueryFactory(EntityManager em) {
        return new JPAQueryFactory(em);
    }
}

 

 

ratingService

@Transactional
    public ApiResponse<RatingResponseDto> RandomRatingGoods() {
        Rating rating = ratingRepository.findRandomRatingWithCountLessThanOrEqual7();
        return new ApiResponse<>(true, new RatingResponseDto(rating), null);
    }

 

ratingRepositorys

public interface RatingRepository extends JpaRepository<Rating, Long>, RatingRepositoryCustom {

}

public interface RatingRepositoryCustom {
    Rating findRandomRatingWithCountLessThanOrEqual7();

}


@RequiredArgsConstructor
public class RatingRepositoryCustomImpl implements RatingRepositoryCustom {
    private final JPAQueryFactory queryFactory;
    @Override
    public Rating findRandomRatingWithCountLessThanOrEqual7() {
        QRating qRating = QRating.rating;
        List<Long> ids = queryFactory.select(qRating.ratingId)
                .from(qRating)
                .where(qRating.ratingCount.loe(7))
                .orderBy(qRating.ratingCount.asc())
                .fetch();

        if (ids.isEmpty()) {
            return null;
        }

        Long randomId = getRandomId(ids);

        return queryFactory.selectFrom(qRating)
                .where(qRating.ratingId.eq(randomId))
                .fetchOne();
    }

    private Long getRandomId(List<Long> ids) {
        int randomIndex = ThreadLocalRandom.current().nextInt(ids.size());
        return ids.get(randomIndex);
    }
}

 

interface는 다중상속이 가능하므로 RatingRepository가 JPARepository와 RatingRepositoryCustom을 상속받는다.

 

RatingRepositoryCustom은 RatingRepository에서 사용할 커스텀 쿼리 메서드를 선언하는 역할을 한다

 

RatingRepositoryCustomImpl은 RatingRepositoryCustom을 실제로 구현하는 구현체이다.

RatingRepositoryCustom에 선언된 쿼리 메서드를 정의하고 실제 DB 쿼리로 매핑하는 역할을 한다.

JPAQueryFactory를 사용하여 QueryDSL을 이용하여 쿼리를 작성하고 실행하도록 작성하였다.

 


 

처음으로 QueryDSL을 사용해봤다.

SQL에 대해 공부를 했었지만 비슷한 것 같으면서도 달라서 헷갈렸다.

익숙해질 수 있도록 많이 사용해봐야겠다.