From 4dd7bfb72ea10a9b62dcd9e2faf658d8a9385f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9A=B0=EB=94=94?= <38103085+EunjiShin@users.noreply.github.com> Date: Fri, 5 Jul 2024 00:44:03 +0900 Subject: [PATCH] =?UTF-8?q?[BSVR-56]=20QueryDSL=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix : 윈도우에서 makeGitHooksExecutable 에러 fix * build(queryDSL): queryDSL 의존성 추가 * feat: queryDSl configuration 추가 * feat: QueryDSL 샘플 코드 추가 * docs: swagger 수정 * docs: editorconfig 설정에서 indent 4space로 조정 --------- Co-authored-by: wjdwnsdnjs13 <67488973+wjdwnsdnjs13@users.noreply.github.com> --- .editorconfig | 2 +- .../member/controller/MemberController.java | 15 +++++++++ infrastructure/jpa/build.gradle.kts | 7 ++++- .../spot/jpa/config/QueryDslConfig.java | 20 ++++++++++++ .../repository/MemberCustomRepository.java | 31 +++++++++++++++++++ .../repository/MemberRepositoryImpl.java | 9 ++++++ .../spot/usecase/port/in/MemberUsecase.java | 4 +++ .../usecase/port/out/MemberRepository.java | 4 +++ .../spot/usecase/service/MemberService.java | 7 +++++ versions.properties | 4 +++ 10 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/config/QueryDslConfig.java create mode 100644 infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberCustomRepository.java diff --git a/.editorconfig b/.editorconfig index e41a4de5..4eab9d38 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,7 @@ [*] charset = utf-8 end_of_line = lf -indent_size = 2 +indent_size = 4 indent_style = space insert_final_newline = false max_line_length = 100 diff --git a/application/src/main/java/org/depromeet/spot/application/member/controller/MemberController.java b/application/src/main/java/org/depromeet/spot/application/member/controller/MemberController.java index f7b9c633..673abfb3 100644 --- a/application/src/main/java/org/depromeet/spot/application/member/controller/MemberController.java +++ b/application/src/main/java/org/depromeet/spot/application/member/controller/MemberController.java @@ -1,16 +1,21 @@ package org.depromeet.spot.application.member.controller; +import java.util.List; + import org.depromeet.spot.application.member.dto.request.MemberRequest; import org.depromeet.spot.application.member.dto.response.MemberResponse; import org.depromeet.spot.usecase.port.in.MemberUsecase; import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.val; @@ -31,4 +36,14 @@ public MemberResponse create(@RequestBody MemberRequest request) { val member = memberUsecase.create(request.name()); return MemberResponse.from(member); } + + @GetMapping + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "이름으로 Member 조회하는 API") + public List findByName( + @RequestParam("name") @Parameter(name = "name", description = "사용자 이름", required = true) + final String name) { + val memberList = memberUsecase.findByName(name); + return memberList.stream().map(MemberResponse::from).toList(); + } } diff --git a/infrastructure/jpa/build.gradle.kts b/infrastructure/jpa/build.gradle.kts index 72d73e5c..5a06ab8d 100644 --- a/infrastructure/jpa/build.gradle.kts +++ b/infrastructure/jpa/build.gradle.kts @@ -5,12 +5,17 @@ dependencies { // spring implementation("org.springframework.boot:spring-boot-starter-data-jpa:_") + // queryDSL + implementation("com.querydsl:querydsl-jpa:_:jakarta") + annotationProcessor("com.querydsl:querydsl-apt:_:jakarta") + annotationProcessor("jakarta.annotation:jakarta.annotation-api") + annotationProcessor("jakarta.persistence:jakarta.persistence-api") + // p6spy implementation("com.github.gavlyukovskiy:p6spy-spring-boot-starter:_") // h2 - DB (또는 도커) 세팅 후 사라질 예정,, runtimeOnly("com.h2database:h2") - } tasks.bootJar { enabled = false } diff --git a/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/config/QueryDslConfig.java b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/config/QueryDslConfig.java new file mode 100644 index 00000000..5b64ca95 --- /dev/null +++ b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/config/QueryDslConfig.java @@ -0,0 +1,20 @@ +package org.depromeet.spot.jpa.config; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +@Configuration +public class QueryDslConfig { + + @PersistenceContext private EntityManager entityManager; + + @Bean + public JPAQueryFactory queryFactory() { + return new JPAQueryFactory(entityManager); + } +} diff --git a/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberCustomRepository.java b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberCustomRepository.java new file mode 100644 index 00000000..f0d490a7 --- /dev/null +++ b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberCustomRepository.java @@ -0,0 +1,31 @@ +package org.depromeet.spot.jpa.member.repository; + +import static org.depromeet.spot.jpa.member.entity.QMemberEntity.memberEntity; + +import java.util.List; + +import org.depromeet.spot.jpa.member.entity.MemberEntity; +import org.springframework.stereotype.Repository; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class MemberCustomRepository { + + private final JPAQueryFactory queryFactory; + + public List findByName(final String name) { + return queryFactory.selectFrom(memberEntity).where(eqMemberName(name)).fetch(); + } + + private BooleanExpression eqMemberName(final String name) { + if (name == null) { + return null; + } + return memberEntity.name.eq(name); + } +} diff --git a/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberRepositoryImpl.java b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberRepositoryImpl.java index 42507851..8c4ebba9 100644 --- a/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberRepositoryImpl.java +++ b/infrastructure/jpa/src/main/java/org/depromeet/spot/jpa/member/repository/MemberRepositoryImpl.java @@ -1,5 +1,7 @@ package org.depromeet.spot.jpa.member.repository; +import java.util.List; + import org.depromeet.spot.domain.member.Member; import org.depromeet.spot.jpa.member.entity.MemberEntity; import org.depromeet.spot.usecase.port.out.MemberRepository; @@ -13,10 +15,17 @@ public class MemberRepositoryImpl implements MemberRepository { private final MemberJpaRepository memberJpaRepository; + private final MemberCustomRepository memberCustomRepository; @Override public Member save(Member member) { val memberEntity = memberJpaRepository.save(MemberEntity.from(member)); return memberEntity.toDomain(); } + + @Override + public List findByName(String name) { + val memberEntities = memberCustomRepository.findByName(name); + return memberEntities.stream().map(MemberEntity::toDomain).toList(); + } } diff --git a/usecase/src/main/java/org/depromeet/spot/usecase/port/in/MemberUsecase.java b/usecase/src/main/java/org/depromeet/spot/usecase/port/in/MemberUsecase.java index 79af200b..42b00e6e 100644 --- a/usecase/src/main/java/org/depromeet/spot/usecase/port/in/MemberUsecase.java +++ b/usecase/src/main/java/org/depromeet/spot/usecase/port/in/MemberUsecase.java @@ -1,8 +1,12 @@ package org.depromeet.spot.usecase.port.in; +import java.util.List; + import org.depromeet.spot.domain.member.Member; public interface MemberUsecase { Member create(String name); + + List findByName(String name); } diff --git a/usecase/src/main/java/org/depromeet/spot/usecase/port/out/MemberRepository.java b/usecase/src/main/java/org/depromeet/spot/usecase/port/out/MemberRepository.java index b7b5fe40..58da7024 100644 --- a/usecase/src/main/java/org/depromeet/spot/usecase/port/out/MemberRepository.java +++ b/usecase/src/main/java/org/depromeet/spot/usecase/port/out/MemberRepository.java @@ -1,8 +1,12 @@ package org.depromeet.spot.usecase.port.out; +import java.util.List; + import org.depromeet.spot.domain.member.Member; public interface MemberRepository { Member save(Member member); + + List findByName(String name); } diff --git a/usecase/src/main/java/org/depromeet/spot/usecase/service/MemberService.java b/usecase/src/main/java/org/depromeet/spot/usecase/service/MemberService.java index 061ec57c..3e04c948 100644 --- a/usecase/src/main/java/org/depromeet/spot/usecase/service/MemberService.java +++ b/usecase/src/main/java/org/depromeet/spot/usecase/service/MemberService.java @@ -1,5 +1,7 @@ package org.depromeet.spot.usecase.service; +import java.util.List; + import org.depromeet.spot.domain.member.Member; import org.depromeet.spot.usecase.port.in.MemberUsecase; import org.depromeet.spot.usecase.port.out.MemberRepository; @@ -19,4 +21,9 @@ public Member create(final String name) { val member = new Member(null, name); return memberRepository.save(member); } + + @Override + public List findByName(final String name) { + return memberRepository.findByName(name); + } } diff --git a/versions.properties b/versions.properties index c3ce1b2e..5844e6f2 100644 --- a/versions.properties +++ b/versions.properties @@ -25,3 +25,7 @@ version.org.springdoc..springdoc-openapi-starter-webmvc-ui=2.5.0 version.com.github.gavlyukovskiy..p6spy-spring-boot-starter=1.9.0 +version.com.querydsl..querydsl-apt=5.0.0 + +version.com.querydsl..querydsl-jpa=5.0.0 +