From 5c466a66c8dcd89190a5652bf186c80249234f5c Mon Sep 17 00:00:00 2001 From: yumzen Date: Sun, 19 Jan 2025 20:29:17 +0900 Subject: [PATCH 1/4] =?UTF-8?q?#314=20Fix:=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/repository/MemberRepository.java | 2 -- .../member/repository/MemberRepositoryCustom.java | 2 ++ .../member/repository/MemberRepositoryImpl.java | 12 ++++++++++++ .../domain/member/service/MemberCommandService.java | 7 +++++-- .../techstack/repository/TechStackRepository.java | 10 ++++++++++ 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/codiary/backend/domain/techstack/repository/TechStackRepository.java diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepository.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepository.java index 70f8d4d7..b58879b9 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepository.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepository.java @@ -10,8 +10,6 @@ public interface MemberRepository extends JpaRepository, MemberRep Boolean existsByNickname(String nickname); - Optional findByEmail(String email); - Optional findByNicknameIgnoreCase(String nickname); //Optional findByNickname(String nickname); diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java index dafc8607..8edab043 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java @@ -5,6 +5,8 @@ import java.util.Optional; public interface MemberRepositoryCustom { + Optional findByEmail(String email); + Optional findMemberWithTechStacksAndProjectsAndTeam(Long userId); Optional findMemberWithTechStacks(Long userId); diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java index 71d325f7..c270a3bc 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java @@ -12,6 +12,7 @@ import static com.codiary.backend.domain.category.entity.QCategory.category; import static com.codiary.backend.domain.member.entity.QMember.member; import static com.codiary.backend.domain.member.entity.QMemberCategory.memberCategory; +import static com.codiary.backend.domain.member.entity.QMemberImage.memberImage; import static com.codiary.backend.domain.techstack.entity.QTechStacks.techStacks; import static com.codiary.backend.domain.project.entity.QProject.project; import static com.codiary.backend.domain.team.entity.QTeamMember.teamMember; @@ -22,6 +23,16 @@ public class MemberRepositoryImpl implements MemberRepositoryCustom { private final JPAQueryFactory queryFactory; + public Optional findByEmail(String email){ + Member fetchedMember = queryFactory + .selectFrom(member) + .leftJoin(member.image, memberImage).fetchJoin() + .where(member.email.eq(email)) + .fetchOne(); + + return Optional.ofNullable(fetchedMember); + } + public Optional findMemberWithTechStacksAndProjectsAndTeam(Long userId) { Member fetchedMember = queryFactory .selectFrom(member) @@ -39,6 +50,7 @@ public Optional findMemberWithTechStacks(Long userId) { Member fetchedMember = queryFactory .selectFrom(member) .leftJoin(member.techStackList, techStacks).fetchJoin() + .leftJoin(member.image, memberImage).fetchJoin() .where(member.memberId.eq(userId)) .fetchOne(); diff --git a/src/main/java/com/codiary/backend/domain/member/service/MemberCommandService.java b/src/main/java/com/codiary/backend/domain/member/service/MemberCommandService.java index e6839b0b..499aac6e 100644 --- a/src/main/java/com/codiary/backend/domain/member/service/MemberCommandService.java +++ b/src/main/java/com/codiary/backend/domain/member/service/MemberCommandService.java @@ -8,6 +8,7 @@ import com.codiary.backend.domain.member.repository.MemberRepository; import com.codiary.backend.domain.techstack.entity.TechStacks; import com.codiary.backend.domain.techstack.enumerate.TechStack; +import com.codiary.backend.domain.techstack.repository.TechStackRepository; import com.codiary.backend.global.apiPayload.ApiResponse; import com.codiary.backend.global.apiPayload.code.status.ErrorStatus; import com.codiary.backend.global.apiPayload.code.status.SuccessStatus; @@ -22,9 +23,11 @@ import java.util.Optional; import java.util.UUID; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -34,6 +37,7 @@ public class MemberCommandService { private final UuidRepository uuidRepository; private final AmazonS3Manager s3Manager; private final MemberImageRepository memberImageRepository; + private final TechStackRepository techStackRepository; @Transactional public Member getRequester() { @@ -93,10 +97,9 @@ public Member addTechStack(Long memberId, TechStack techstack) { Member member = memberRepository.findMemberWithTechStacks(memberId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND)); - if (member.getTechStackList().stream().anyMatch(stack -> stack.getName().equals(techstack))) { + if (techStackRepository.existsByNameAndMember(techstack, member)) { throw new GeneralException(ErrorStatus.TECH_STACK_ALREADY_EXISTS); } - //business logic: 기술스택 추가 List techStackList = Optional.of(member.getTechStackList()).orElse(new ArrayList<>()); TechStacks newTechStack = new TechStacks(techstack, member); diff --git a/src/main/java/com/codiary/backend/domain/techstack/repository/TechStackRepository.java b/src/main/java/com/codiary/backend/domain/techstack/repository/TechStackRepository.java new file mode 100644 index 00000000..89f847db --- /dev/null +++ b/src/main/java/com/codiary/backend/domain/techstack/repository/TechStackRepository.java @@ -0,0 +1,10 @@ +package com.codiary.backend.domain.techstack.repository; + +import com.codiary.backend.domain.member.entity.Member; +import com.codiary.backend.domain.techstack.entity.TechStacks; +import com.codiary.backend.domain.techstack.enumerate.TechStack; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TechStackRepository extends JpaRepository { + boolean existsByNameAndMember(TechStack name, Member member); +} From ae2a02ab3f8df0cf27e1e346e1899904a54a9cfb Mon Sep 17 00:00:00 2001 From: yumzen Date: Sun, 19 Jan 2025 21:10:16 +0900 Subject: [PATCH 2/4] =?UTF-8?q?#314=20Fix:=20imageURL=20=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/dto/response/MemberResponseDTO.java | 8 +++++++- .../member/repository/MemberRepositoryCustom.java | 2 ++ .../member/repository/MemberRepositoryImpl.java | 11 +++++++++++ .../domain/member/service/MemberQueryService.java | 6 +----- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/codiary/backend/domain/member/dto/response/MemberResponseDTO.java b/src/main/java/com/codiary/backend/domain/member/dto/response/MemberResponseDTO.java index 529a6099..66751aa7 100644 --- a/src/main/java/com/codiary/backend/domain/member/dto/response/MemberResponseDTO.java +++ b/src/main/java/com/codiary/backend/domain/member/dto/response/MemberResponseDTO.java @@ -34,7 +34,13 @@ public record TokenRefreshResponseDTO( @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @Builder - public record MemberImageDTO(String url) {} + public record MemberImageDTO(String url) { + public static MemberImageDTO of(String url) { + return MemberImageDTO.builder() + .url(url) + .build(); + } + } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java index 8edab043..20924000 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryCustom.java @@ -1,5 +1,6 @@ package com.codiary.backend.domain.member.repository; +import com.codiary.backend.domain.member.dto.response.MemberResponseDTO; import com.codiary.backend.domain.member.entity.Member; import java.util.Optional; @@ -16,4 +17,5 @@ public interface MemberRepositoryCustom { Optional findByIdWithFollowings(Long id); Optional findByIdWithFollowers(Long id); Optional findByIdWithCategory(Long id); + MemberResponseDTO.MemberImageDTO findProfileImageUrl(Long id); } diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java index c270a3bc..8a86c886 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java @@ -1,5 +1,6 @@ package com.codiary.backend.domain.member.repository; +import com.codiary.backend.domain.member.dto.response.MemberResponseDTO; import com.codiary.backend.domain.member.entity.Member; import com.codiary.backend.domain.team.entity.TeamMember; import com.codiary.backend.domain.project.entity.Project; @@ -128,4 +129,14 @@ public Optional findByIdWithCategory(Long id) { return Optional.ofNullable(fetchedMember); } + + public MemberResponseDTO.MemberImageDTO findProfileImageUrl(Long id) { + Optional imageUrl = Optional.ofNullable(queryFactory + .select(member.image.imageUrl) + .from(member) + .where(member.memberId.eq(id)) + .fetchOne()); + + return MemberResponseDTO.MemberImageDTO.of(imageUrl.orElse("")); + } } diff --git a/src/main/java/com/codiary/backend/domain/member/service/MemberQueryService.java b/src/main/java/com/codiary/backend/domain/member/service/MemberQueryService.java index d8254c12..ef39f549 100644 --- a/src/main/java/com/codiary/backend/domain/member/service/MemberQueryService.java +++ b/src/main/java/com/codiary/backend/domain/member/service/MemberQueryService.java @@ -9,7 +9,6 @@ import com.codiary.backend.global.apiPayload.code.status.ErrorStatus; import com.codiary.backend.global.apiPayload.code.status.SuccessStatus; import com.codiary.backend.global.apiPayload.exception.GeneralException; -import com.codiary.backend.global.apiPayload.exception.handler.MemberHandler; import com.codiary.backend.domain.member.entity.Member; import com.codiary.backend.domain.member.dto.response.MemberResponseDTO; import lombok.RequiredArgsConstructor; @@ -30,10 +29,7 @@ public class MemberQueryService{ private final PostRepository postRepository; public ApiResponse getProfileImage(Long memberId) { - Member user = memberRepository.findById(memberId).orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND)); - String url = (user.getImage() != null) ? user.getImage().getImageUrl() : ""; - MemberResponseDTO.MemberImageDTO response = new MemberResponseDTO.MemberImageDTO(url); - return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, response); + return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, memberRepository.findProfileImageUrl(memberId)); } public Member getUserProfile(Long memberId) { From ec519f73652c245b6b78d54c2d959e85efc082b9 Mon Sep 17 00:00:00 2001 From: yumzen Date: Mon, 20 Jan 2025 17:50:00 +0900 Subject: [PATCH 3/4] =?UTF-8?q?#314=20Fix:=20followMember=20N+1=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/repository/MemberRepositoryImpl.java | 3 +++ .../codiary/backend/domain/member/service/FollowService.java | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java index 8a86c886..a8165a72 100644 --- a/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/codiary/backend/domain/member/repository/MemberRepositoryImpl.java @@ -73,6 +73,7 @@ public Optional findByIdWithAndFollowersAndFollowings(Long id) { .selectFrom(member) .leftJoin(member.followers) .leftJoin(member.followings) + .leftJoin(member.image, memberImage).fetchJoin() .where(member.memberId.eq(id)) .fetchOne(); @@ -83,6 +84,7 @@ public Optional findByIdWithFollowings(Long id) { Member fetchedMember = queryFactory .selectFrom(member) .leftJoin(member.followings) + .leftJoin(member.image, memberImage).fetchJoin() .where(member.memberId.eq(id)) .fetchOne(); @@ -93,6 +95,7 @@ public Optional findByIdWithFollowers(Long id) { Member fetchedMember = queryFactory .selectFrom(member) .leftJoin(member.followers) + .leftJoin(member.image, memberImage).fetchJoin() .where(member.memberId.eq(id)) .fetchOne(); diff --git a/src/main/java/com/codiary/backend/domain/member/service/FollowService.java b/src/main/java/com/codiary/backend/domain/member/service/FollowService.java index 54af2fae..3b563a0e 100644 --- a/src/main/java/com/codiary/backend/domain/member/service/FollowService.java +++ b/src/main/java/com/codiary/backend/domain/member/service/FollowService.java @@ -7,13 +7,14 @@ import com.codiary.backend.global.apiPayload.code.status.ErrorStatus; import com.codiary.backend.global.apiPayload.exception.GeneralException; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; - +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -24,6 +25,7 @@ public class FollowService { @Transactional public Follow follow(Long toId, Member fromMember) { //Validation: fromMember와 toMember 존재 여부 확인/ 자기 자신 팔로우 불가/ 이미 팔로우 중인지 확인 + fromMember = memberRepository.findByIdWithAndFollowersAndFollowings(fromMember.getMemberId()).orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND)); Member toMember = memberRepository.findByIdWithFollowers(toId) From fd6c79380173ee6c4610b983239de64346cc406a Mon Sep 17 00:00:00 2001 From: yumzen Date: Mon, 20 Jan 2025 18:35:21 +0900 Subject: [PATCH 4/4] =?UTF-8?q?#314=20Fix:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=9A=94=EC=B2=AD=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/member/controller/MemberController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/codiary/backend/domain/member/controller/MemberController.java b/src/main/java/com/codiary/backend/domain/member/controller/MemberController.java index bb2f33d4..f81f8462 100644 --- a/src/main/java/com/codiary/backend/domain/member/controller/MemberController.java +++ b/src/main/java/com/codiary/backend/domain/member/controller/MemberController.java @@ -54,8 +54,9 @@ public ApiResponse getProfileImage(@PathVariab @GetMapping("/profile/{member_id}") @Operation(summary = "사용자 프로필 기본 정보 조회", description = "마이페이지 사용자 정보 조회 기능") public ApiResponse getUserProfile(@AuthenticationPrincipal CustomMemberDetails memberDetails, @PathVariable(value = "member_id") Long memberId){ + Member currentMember = memberQueryService.getUserInfo(memberDetails.getId()); Member user = memberQueryService.getUserProfile(memberId); - return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, MemberConverter.toSimpleMemberResponseDto(user, user)); + return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, MemberConverter.toSimpleMemberResponseDto(currentMember, user)); } @PutMapping("/info")