Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.example.solidconnection.location.region.domain.Region;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -10,4 +11,6 @@ public interface RegionRepository extends JpaRepository<Region, Long> {

@Query("SELECT r FROM Region r WHERE r.koreanName IN :names")
List<Region> findByKoreanNames(@Param(value = "names") List<String> names);

Optional<Region> findByKoreanName(String koreanName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.example.solidconnection.mentor.domain.Mentor;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.university.domain.University;
import java.util.List;

public record MentorDetailResponse(
Expand All @@ -19,13 +20,14 @@ public record MentorDetailResponse(
boolean isApplied
) {

public static MentorDetailResponse of(Mentor mentor, SiteUser mentorUser, boolean isApplied) {
public static MentorDetailResponse of(Mentor mentor, SiteUser mentorUser,
University university, boolean isApplied) {
return new MentorDetailResponse(
mentor.getId(),
mentorUser.getNickname(),
mentorUser.getProfileImageUrl(),
"국가", // todo: 교환학생 기록이 인증되면 추가
"대학 이름", // todo: 교환학생 기록이 인증되면 추가
university.getCountry().getKoreanName(),
university.getKoreanName(),
Comment on lines +29 to +30
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

university는 country 를 eager로 fetch 해오기 때문에
여기에서 initialization exception이 발생하진 않습니다~
(혹시나 아리송 하실까봐 설명 덧붙입니다 ㅎㅎ)

mentor.getTerm(),
mentor.getMenteeCount(),
mentor.isHasBadge(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.example.solidconnection.mentor.domain.Mentor;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.university.domain.University;
import java.util.List;

public record MentorMyPageResponse(
Expand All @@ -17,13 +18,13 @@ public record MentorMyPageResponse(
List<ChannelResponse> channels
) {

public static MentorMyPageResponse of(Mentor mentor, SiteUser siteUser) {
public static MentorMyPageResponse of(Mentor mentor, SiteUser siteUser, University university) {
return new MentorMyPageResponse(
mentor.getId(),
siteUser.getProfileImageUrl(),
siteUser.getNickname(),
"국가", // todo: 교환학생 기록이 인증되면 추가
"대학 이름",
university.getCountry().getKoreanName(),
university.getKoreanName(),
mentor.getTerm(),
mentor.getMenteeCount(),
mentor.isHasBadge(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.example.solidconnection.mentor.domain.Mentor;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.university.domain.University;
import java.util.List;

public record MentorPreviewResponse(
Expand All @@ -18,13 +19,14 @@ public record MentorPreviewResponse(
boolean isApplied
) {

public static MentorPreviewResponse of(Mentor mentor, SiteUser mentorUser, boolean isApplied) {
public static MentorPreviewResponse of(Mentor mentor, SiteUser mentorUser,
University university, boolean isApplied) {
return new MentorPreviewResponse(
mentor.getId(),
mentorUser.getNickname(),
mentorUser.getProfileImageUrl(),
"국가", // todo: 교환학생 기록이 인증되면 추가
"대학 이름", // todo: 교환학생 기록이 인증되면 추가
university.getCountry().getKoreanName(),
university.getKoreanName(),
mentor.getTerm(),
mentor.getMenteeCount(),
mentor.isHasBadge(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.example.solidconnection.mentor.domain.Mentoring;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.university.domain.University;
import com.example.solidconnection.university.repository.UniversityRepository;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -21,6 +23,7 @@ public class MentorBatchQueryRepository { // 연관관계가 설정되지 않은

private final SiteUserRepository siteUserRepository;
private final MentoringRepository mentoringRepository;
private final UniversityRepository universityRepository;

public Map<Long, SiteUser> getMentorIdToSiteUserMap(List<Mentor> mentors) {
List<Long> mentorUserIds = mentors.stream().map(Mentor::getSiteUserId).toList();
Expand All @@ -40,6 +43,24 @@ public Map<Long, SiteUser> getMentorIdToSiteUserMap(List<Mentor> mentors) {
));
}

public Map<Long, University> getMentorIdToUniversityMap(List<Mentor> mentors) {
List<Long> universityIds = mentors.stream().map(Mentor::getUniversityId).distinct().toList();
List<University> universities = universityRepository.findAllById(universityIds);
Map<Long, University> universityIdToUniversityMap = universities.stream()
.collect(Collectors.toMap(University::getId, Function.identity()));

return mentors.stream().collect(Collectors.toMap(
Mentor::getId,
mentor -> {
University university = universityIdToUniversityMap.get(mentor.getUniversityId());
if (university == null) { // mentor.university_id에 해당하는 대학이 없으면 정합성 문제가 발생한 것
throw new CustomException(DATA_INTEGRITY_VIOLATION, "mentor.university_id 에 해당하는 university 존재하지 않음");
}
return university;
}
));
}

public Map<Long, Boolean> getMentorIdToIsApplied(List<Mentor> mentors, long currentUserId) {
List<Long> mentorIds = mentors.stream().map(Mentor::getId).toList();
List<Mentoring> appliedMentorings = mentoringRepository.findAllByMentorIdInAndMenteeId(mentorIds, currentUserId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.example.solidconnection.mentor.repository;

import com.example.solidconnection.location.region.domain.Region;
import com.example.solidconnection.mentor.domain.Mentor;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface MentorRepository extends JpaRepository<Mentor, Long> {

Expand All @@ -13,4 +16,11 @@ public interface MentorRepository extends JpaRepository<Mentor, Long> {
Optional<Mentor> findBySiteUserId(long siteUserId);

Slice<Mentor> findAllBy(Pageable pageable);

@Query("""
SELECT m FROM Mentor m
JOIN University u ON m.universityId = u.id
WHERE u.region = :region
""")
Slice<Mentor> findAllByRegion(@Param("region") Region region, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.example.solidconnection.common.exception.ErrorCode.CHANNEL_REGISTRATION_LIMIT_EXCEEDED;
import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND;
import static com.example.solidconnection.common.exception.ErrorCode.UNIVERSITY_NOT_FOUND;
import static com.example.solidconnection.common.exception.ErrorCode.USER_NOT_FOUND;

import com.example.solidconnection.common.exception.CustomException;
Expand All @@ -13,6 +14,8 @@
import com.example.solidconnection.mentor.repository.MentorRepository;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.university.domain.University;
import com.example.solidconnection.university.repository.UniversityRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -28,14 +31,17 @@ public class MentorMyPageService {

private final MentorRepository mentorRepository;
private final SiteUserRepository siteUserRepository;
private final UniversityRepository universityRepository;

@Transactional(readOnly = true)
public MentorMyPageResponse getMentorMyPage(long siteUserId) {
SiteUser siteUser = siteUserRepository.findById(siteUserId)
.orElseThrow(() -> new CustomException(USER_NOT_FOUND));
Mentor mentor = mentorRepository.findBySiteUserId(siteUser.getId())
.orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND));
return MentorMyPageResponse.of(mentor, siteUser);
University university = universityRepository.findById(mentor.getUniversityId())
.orElseThrow(() -> new CustomException(UNIVERSITY_NOT_FOUND));
return MentorMyPageResponse.of(mentor, siteUser, university);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.example.solidconnection.mentor.service;

import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND;
import static com.example.solidconnection.common.exception.ErrorCode.UNIVERSITY_NOT_FOUND;

import com.example.solidconnection.common.dto.SliceResponse;
import com.example.solidconnection.common.exception.CustomException;
import com.example.solidconnection.common.exception.ErrorCode;
import com.example.solidconnection.location.region.domain.Region;
import com.example.solidconnection.location.region.repository.RegionRepository;
import com.example.solidconnection.mentor.domain.Mentor;
import com.example.solidconnection.mentor.dto.MentorDetailResponse;
import com.example.solidconnection.mentor.dto.MentorPreviewResponse;
Expand All @@ -12,6 +16,8 @@
import com.example.solidconnection.mentor.repository.MentoringRepository;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.university.domain.University;
import com.example.solidconnection.university.repository.UniversityRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -29,36 +35,51 @@ public class MentorQueryService {
private final MentoringRepository mentoringRepository;
private final SiteUserRepository siteUserRepository;
private final MentorBatchQueryRepository mentorBatchQueryRepository;
private final UniversityRepository universityRepository;
private final RegionRepository regionRepository;

@Transactional(readOnly = true)
public MentorDetailResponse getMentorDetails(long mentorId, long currentUserId) {
Mentor mentor = mentorRepository.findById(mentorId)
.orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND));
University university = universityRepository.findById(mentor.getUniversityId())
.orElseThrow(() -> new CustomException(UNIVERSITY_NOT_FOUND));
SiteUser mentorUser = siteUserRepository.findById(mentor.getSiteUserId())
.orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND));
boolean isApplied = mentoringRepository.existsByMentorIdAndMenteeId(mentorId, currentUserId);

return MentorDetailResponse.of(mentor, mentorUser, isApplied);
return MentorDetailResponse.of(mentor, mentorUser, university, isApplied);
}

@Transactional(readOnly = true)
public SliceResponse<MentorPreviewResponse> getMentorPreviews(String region, long currentUserId, Pageable pageable) { // todo: 멘토의 '인증' 작업 후 region 필터링 추가
Slice<Mentor> mentorSlice = mentorRepository.findAllBy(pageable);
public SliceResponse<MentorPreviewResponse> getMentorPreviews(String regionKoreanName, long currentUserId, Pageable pageable) {
Slice<Mentor> mentorSlice = filterMentorsByRegion(regionKoreanName, pageable);
List<Mentor> mentors = mentorSlice.toList();
List<MentorPreviewResponse> content = getMentorPreviewResponses(mentors, currentUserId);
List<MentorPreviewResponse> content = buildMentorPreviewsWithBatchQuery(mentors, currentUserId);

return SliceResponse.of(content, mentorSlice);
}

private List<MentorPreviewResponse> getMentorPreviewResponses(List<Mentor> mentors, long currentUserId) {
private Slice<Mentor> filterMentorsByRegion(String regionKoreanName, Pageable pageable) {
if (regionKoreanName == null || regionKoreanName.isEmpty()) {
return mentorRepository.findAll(pageable);
}
Region region = regionRepository.findByKoreanName(regionKoreanName)
.orElseThrow(() -> new CustomException(ErrorCode.REGION_NOT_FOUND_BY_KOREAN_NAME));
return mentorRepository.findAllByRegion(region, pageable);
}

private List<MentorPreviewResponse> buildMentorPreviewsWithBatchQuery(List<Mentor> mentors, long currentUserId) {
Map<Long, SiteUser> mentorIdToSiteUser = mentorBatchQueryRepository.getMentorIdToSiteUserMap(mentors);
Map<Long, University> mentorIdToUniversity = mentorBatchQueryRepository.getMentorIdToUniversityMap(mentors);
Map<Long, Boolean> mentorIdToIsApplied = mentorBatchQueryRepository.getMentorIdToIsApplied(mentors, currentUserId);

List<MentorPreviewResponse> mentorPreviews = new ArrayList<>();
for (Mentor mentor : mentors) {
SiteUser mentorUser = mentorIdToSiteUser.get(mentor.getId());
University university = mentorIdToUniversity.get(mentor.getId());
boolean isApplied = mentorIdToIsApplied.get(mentor.getId());
MentorPreviewResponse response = MentorPreviewResponse.of(mentor, mentorUser, isApplied);
MentorPreviewResponse response = MentorPreviewResponse.of(mentor, mentorUser, university, isApplied);
mentorPreviews.add(response);
}
return mentorPreviews;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.fixture.SiteUserFixture;
import com.example.solidconnection.support.TestContainerSpringBootTest;
import com.example.solidconnection.university.domain.University;
import com.example.solidconnection.university.fixture.UniversityFixture;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -32,7 +34,10 @@ class MentorBatchQueryRepositoryTest {
@Autowired
private SiteUserFixture siteUserFixture;

private long universityId = 1L; // todo: 멘토 인증 기능 추가 변경 필요
@Autowired
private UniversityFixture universityFixture;

private University university1, university2;
private Mentor mentor1, mentor2;
private SiteUser mentorUser1, mentorUser2, currentUser;

Expand All @@ -41,8 +46,10 @@ void setUp() {
currentUser = siteUserFixture.사용자(1, "사용자");
mentorUser1 = siteUserFixture.사용자(2, "멘토1");
mentorUser2 = siteUserFixture.사용자(3, "멘토2");
mentor1 = mentorFixture.멘토(mentorUser1.getId(), universityId);
mentor2 = mentorFixture.멘토(mentorUser2.getId(), universityId);
university1 = universityFixture.코펜하겐IT_대학();
university2 = universityFixture.메모리얼_대학_세인트존스();
mentor1 = mentorFixture.멘토(mentorUser1.getId(), university1.getId());
mentor2 = mentorFixture.멘토(mentorUser2.getId(), university2.getId());
}

@Test
Expand All @@ -60,6 +67,21 @@ void setUp() {
);
}

@Test
void 멘토_ID_와_멘토의_파견_대학교를_매핑한다() {
// given
List<Mentor> mentors = List.of(mentor1, mentor2);

// when
Map<Long, University> mentorIdToUniversity = mentorBatchQueryRepository.getMentorIdToUniversityMap(mentors);

// then
assertAll(
() -> assertThat(mentorIdToUniversity.get(mentor1.getId()).getId()).isEqualTo(university1.getId()),
() -> assertThat(mentorIdToUniversity.get(mentor2.getId()).getId()).isEqualTo(university2.getId())
);
}

@Test
void 멘토_ID_와_현재_사용자의_지원_여부를_매핑한다() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.fixture.SiteUserFixture;
import com.example.solidconnection.support.TestContainerSpringBootTest;
import com.example.solidconnection.university.domain.University;
import com.example.solidconnection.university.fixture.UniversityFixture;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -44,17 +46,21 @@ class MentorMyPageServiceTest {
@Autowired
private MentorRepository mentorRepository;

@Autowired
private UniversityFixture universityFixture;

@Autowired
private ChannelRepositoryForTest channelRepositoryForTest;

private SiteUser mentorUser;
private Mentor mentor;
private long universityId = 1L;
private University university;

@BeforeEach
void setUp() {
university = universityFixture.메이지_대학();
mentorUser = siteUserFixture.멘토(1, "멘토");
mentor = mentorFixture.멘토(mentorUser.getId(), universityId);
mentor = mentorFixture.멘토(mentorUser.getId(), university.getId());
}

@Nested
Expand All @@ -73,6 +79,8 @@ class 멘토의_마이_페이지를_조회한다 {
assertAll(
() -> assertThat(response.id()).isEqualTo(mentor.getId()),
() -> assertThat(response.nickname()).isEqualTo(mentorUser.getNickname()),
() -> assertThat(response.universityName()).isEqualTo(university.getKoreanName()),
() -> assertThat(response.country()).isEqualTo(university.getCountry().getKoreanName()),
() -> assertThat(response.channels()).extracting(ChannelResponse::url)
.containsExactly(channel1.getUrl(), channel2.getUrl())
);
Expand Down
Loading
Loading