From 996a53586e0f0d9a3e0a3ef8d3a9b6324f6c12d8 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 13:52:00 +0900 Subject: [PATCH 01/14] =?UTF-8?q?refactor:=20Application=20Entity=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20-=20UniversityInfoForApply=20FK=EB=A7=A4?= =?UTF-8?q?=ED=95=91=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20Long=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD=20-=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20updateUniver?= =?UTF-8?q?sityChoice=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/domain/Application.java | 51 +++++++------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/domain/Application.java b/src/main/java/com/example/solidconnection/application/domain/Application.java index 98342ca88..b4b62fb15 100644 --- a/src/main/java/com/example/solidconnection/application/domain/Application.java +++ b/src/main/java/com/example/solidconnection/application/domain/Application.java @@ -1,7 +1,6 @@ package com.example.solidconnection.application.domain; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.university.domain.UniversityInfoForApply; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -54,14 +53,14 @@ public class Application { @Column private boolean isDelete = false; - @ManyToOne(fetch = FetchType.LAZY) - private UniversityInfoForApply firstChoiceUniversity; + @Column + private Long firstChoiceUniversityApplyInfoId; - @ManyToOne(fetch = FetchType.LAZY) - private UniversityInfoForApply secondChoiceUniversity; + @Column + private Long secondChoiceUniversityApplyInfoId; - @ManyToOne(fetch = FetchType.LAZY) - private UniversityInfoForApply thirdChoiceUniversity; + @Column + private Long thirdChoiceUniversityApplyInfoId; @ManyToOne(fetch = FetchType.LAZY) private SiteUser siteUser; @@ -85,18 +84,18 @@ public Application( LanguageTest languageTest, String term, Integer updateCount, - UniversityInfoForApply firstChoiceUniversity, - UniversityInfoForApply secondChoiceUniversity, - UniversityInfoForApply thirdChoiceUniversity, + Long firstChoiceUniversityApplyInfoId, + Long secondChoiceUniversityApplyInfoId, + Long thirdChoiceUniversityApplyInfoId, String nicknameForApply) { this.siteUser = siteUser; this.gpa = gpa; this.languageTest = languageTest; this.term = term; this.updateCount = updateCount; - this.firstChoiceUniversity = firstChoiceUniversity; - this.secondChoiceUniversity = secondChoiceUniversity; - this.thirdChoiceUniversity = thirdChoiceUniversity; + this.firstChoiceUniversityApplyInfoId = firstChoiceUniversityApplyInfoId; + this.secondChoiceUniversityApplyInfoId = secondChoiceUniversityApplyInfoId; + this.thirdChoiceUniversityApplyInfoId = thirdChoiceUniversityApplyInfoId; this.nicknameForApply = nicknameForApply; this.verifyStatus = PENDING; } @@ -106,18 +105,18 @@ public Application( Gpa gpa, LanguageTest languageTest, String term, - UniversityInfoForApply firstChoiceUniversity, - UniversityInfoForApply secondChoiceUniversity, - UniversityInfoForApply thirdChoiceUniversity, + Long firstChoiceUniversityApplyInfoId, + Long secondChoiceUniversityApplyInfoId, + Long thirdChoiceUniversityApplyInfoId, String nicknameForApply) { this.siteUser = siteUser; this.gpa = gpa; this.languageTest = languageTest; this.term = term; this.updateCount = 1; - this.firstChoiceUniversity = firstChoiceUniversity; - this.secondChoiceUniversity = secondChoiceUniversity; - this.thirdChoiceUniversity = thirdChoiceUniversity; + this.firstChoiceUniversityApplyInfoId = firstChoiceUniversityApplyInfoId; + this.secondChoiceUniversityApplyInfoId = secondChoiceUniversityApplyInfoId; + this.thirdChoiceUniversityApplyInfoId = thirdChoiceUniversityApplyInfoId; this.nicknameForApply = nicknameForApply; this.verifyStatus = PENDING; } @@ -125,18 +124,4 @@ public Application( public void setIsDeleteTrue() { this.isDelete = true; } - - public void updateUniversityChoice( - UniversityInfoForApply firstChoiceUniversity, - UniversityInfoForApply secondChoiceUniversity, - UniversityInfoForApply thirdChoiceUniversity, - String nicknameForApply) { - if (this.firstChoiceUniversity != null) { - this.updateCount++; - } - this.firstChoiceUniversity = firstChoiceUniversity; - this.secondChoiceUniversity = secondChoiceUniversity; - this.thirdChoiceUniversity = thirdChoiceUniversity; - this.nicknameForApply = nicknameForApply; - } } From 2a9064e15df8f3bae77c85e9331eaa195ddf952d Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 14:04:55 +0900 Subject: [PATCH 02/14] =?UTF-8?q?refactor:=20ApplicationQueryService=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20-=20AS-IS:=20=EA=B0=81=20=EC=A7=80?= =?UTF-8?q?=EB=A7=9D=EB=B3=84=EB=A1=9C=20Repository=EB=A5=BC=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=ED=95=98=EC=97=AC=20N+1=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=EB=8B=A8=EC=9D=BC=ED=82=A4=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20=EC=BA=90=EC=8B=B1=20-=20TO-BE:=20=EB=A7=A4?= =?UTF-8?q?=ED=95=91=20=EC=A0=9C=EA=B1=B0=20=ED=9B=84=20=EC=A7=81=EC=A0=91?= =?UTF-8?q?=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EB=B6=84=EB=A5=98?= =?UTF-8?q?=ED=95=98=EC=97=AC=20N+1=EB=AC=B8=EC=A0=9C=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20=EB=B0=8F=20=EC=84=B1=EB=8A=A5=20=ED=96=A5=EC=83=81=20?= =?UTF-8?q?=EC=BA=90=EC=8B=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApplicationQueryService.java | 155 +++++++++--------- 1 file changed, 75 insertions(+), 80 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java index e13ca7e3f..60eb8659d 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java @@ -6,10 +6,8 @@ import com.example.solidconnection.application.dto.ApplicationsResponse; import com.example.solidconnection.application.dto.UniversityApplicantsResponse; import com.example.solidconnection.application.repository.ApplicationRepository; -import com.example.solidconnection.cache.annotation.ThunderingHerdCaching; import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.university.domain.University; import com.example.solidconnection.university.domain.UniversityInfoForApply; import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; import com.example.solidconnection.university.repository.custom.UniversityFilterRepositoryImpl; @@ -18,12 +16,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Function; +import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.example.solidconnection.common.exception.ErrorCode.APPLICATION_NOT_APPROVED; @@ -38,53 +33,92 @@ public class ApplicationQueryService { @Value("${university.term}") public String term; - /* - * 다른 지원자들의 성적을 조회한다. - * - 유저가 다른 지원자들을 볼 수 있는지 검증한다. - * - 지역과 키워드를 통해 대학을 필터링한다. - * - 지역은 영어 대문자로 받는다 e.g. ASIA - * - 1지망, 2지망 지원자들을 조회한다. - * */ @Transactional(readOnly = true) - // todo: 임시로 단일 키로 캐시 적용. 추후 캐싱 전략 재검토 필요. - @ThunderingHerdCaching(key = "applications:all", cacheManager = "customCacheManager", ttlSec = 86400) public ApplicationsResponse getApplicants(SiteUser siteUser, String regionCode, String keyword) { - // 국가와 키워드와 지역을 통해 대학을 필터링한다. - List universities - = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); - - // 1지망, 2지망, 3지망 지원자들을 조회한다. - List firstChoiceApplicants = getFirstChoiceApplicants(universities, siteUser, term); - List secondChoiceApplicants = getSecondChoiceApplicants(universities, siteUser, term); - List thirdChoiceApplicants = getThirdChoiceApplicants(universities, siteUser, term); - return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); + // 1. 대학 ID 필터링 (regionCode, keyword) + List universityIds = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); + if (universityIds.isEmpty()) return new ApplicationsResponse(List.of(), List.of(), List.of()); + + // 2. 조건에 맞는 모든 Application 한 번에 조회 + List applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); + + // 3. 대학정보 조회 + List universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); + + // 4. 지원서 분류 및 DTO 변환 + return classifyApplicationsByChoice(universityInfos, applications, siteUser); } @Transactional(readOnly = true) public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { Application userLatestApplication = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term); - List userAppliedUniversities = Arrays.asList( - Optional.ofNullable(userLatestApplication.getFirstChoiceUniversity()) - .map(UniversityInfoForApply::getUniversity) - .orElse(null), - Optional.ofNullable(userLatestApplication.getSecondChoiceUniversity()) - .map(UniversityInfoForApply::getUniversity) - .orElse(null), - Optional.ofNullable(userLatestApplication.getThirdChoiceUniversity()) - .map(UniversityInfoForApply::getUniversity) - .orElse(null) - ).stream() + + List universityIds = Stream.of( + userLatestApplication.getFirstChoiceUniversityApplyInfoId(), + userLatestApplication.getSecondChoiceUniversityApplyInfoId(), + userLatestApplication.getThirdChoiceUniversityApplyInfoId() + ) .filter(Objects::nonNull) .collect(Collectors.toList()); - List firstChoiceApplicants = getFirstChoiceApplicants(userAppliedUniversities, siteUser, term); - List secondChoiceApplicants = getSecondChoiceApplicants(userAppliedUniversities, siteUser, term); - List thirdChoiceApplicants = getThirdChoiceApplicants(userAppliedUniversities, siteUser, term); + if (universityIds.isEmpty()) { + return new ApplicationsResponse(List.of(), List.of(), List.of()); + } + + List applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); + List universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); + + return classifyApplicationsByChoice(universityInfos, applications, siteUser); + } + + private ApplicationsResponse classifyApplicationsByChoice( + List universityInfos, + List applications, + SiteUser siteUser) { + + Map> firstChoiceMap = new HashMap<>(); + Map> secondChoiceMap = new HashMap<>(); + Map> thirdChoiceMap = new HashMap<>(); + + for (Application a : applications) { + if (a.getFirstChoiceUniversityApplyInfoId() != null) { + firstChoiceMap.computeIfAbsent(a.getFirstChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); + } + if (a.getSecondChoiceUniversityApplyInfoId() != null) { + secondChoiceMap.computeIfAbsent(a.getSecondChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); + } + if (a.getThirdChoiceUniversityApplyInfoId() != null) { + thirdChoiceMap.computeIfAbsent(a.getThirdChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); + } + } + + List firstChoiceApplicants = universityInfos.stream() + .map(uia -> UniversityApplicantsResponse.of( + uia, + firstChoiceMap.getOrDefault(uia.getId(), List.of()).stream() + .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) + .toList())) + .toList(); + + List secondChoiceApplicants = universityInfos.stream() + .map(uia -> UniversityApplicantsResponse.of( + uia, + secondChoiceMap.getOrDefault(uia.getId(), List.of()).stream() + .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) + .toList())) + .toList(); + + List thirdChoiceApplicants = universityInfos.stream() + .map(uia -> UniversityApplicantsResponse.of( + uia, + thirdChoiceMap.getOrDefault(uia.getId(), List.of()).stream() + .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) + .toList())) + .toList(); + return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); } - // 학기별로 상태가 관리된다. - // 금학기에 지원이력이 있는 사용자만 지원정보를 확인할 수 있도록 한다. @Transactional(readOnly = true) public void validateSiteUserCanViewApplicants(SiteUser siteUser) { VerifyStatus verifyStatus = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term).getVerifyStatus(); @@ -92,43 +126,4 @@ public void validateSiteUserCanViewApplicants(SiteUser siteUser) { throw new CustomException(APPLICATION_NOT_APPROVED); } } - - private List getFirstChoiceApplicants(List universities, SiteUser siteUser, String term) { - return getApplicantsByChoice( - universities, - siteUser, - uia -> applicationRepository.findAllByFirstChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) - ); - } - - private List getSecondChoiceApplicants(List universities, SiteUser siteUser, String term) { - return getApplicantsByChoice( - universities, - siteUser, - uia -> applicationRepository.findAllBySecondChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) - ); - } - - private List getThirdChoiceApplicants(List universities, SiteUser siteUser, String term) { - return getApplicantsByChoice( - universities, - siteUser, - uia -> applicationRepository.findAllByThirdChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) - ); - } - - private List getApplicantsByChoice( - List searchedUniversities, - SiteUser siteUser, - Function> findApplicationsByChoice) { - return universityInfoForApplyRepository.findByUniversitiesAndTerm(searchedUniversities, term).stream() - .map(universityInfoForApply -> UniversityApplicantsResponse.of( - universityInfoForApply, - findApplicationsByChoice.apply(universityInfoForApply).stream() - .map(ap -> ApplicantResponse.of( - ap, - Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) - .toList())) - .toList(); - } } From addad7839f925ec4e283be07794fbbb37c2dc83a Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 14:13:29 +0900 Subject: [PATCH 03/14] =?UTF-8?q?refactor:=20University=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20Repository=20=EB=B3=80=EA=B2=BD=20-=20AS-IS:=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20Repository=EC=97=90=EC=84=9C=20University=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B0=98=ED=99=98=20-=20TO-BE:?= =?UTF-8?q?=20Entity=EB=B3=80=EA=B2=BD,=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=ED=99=98=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=B0=20=EB=B0=98=ED=99=98=ED=83=80=EC=9E=85=20Lon?= =?UTF-8?q?g=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20findByIdsWithUnivers?= =?UTF-8?q?ityAndLocation=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EA=B2=8C=20=EB=90=9C=20getUniversityInfoForApplyByIdAndTerm=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniversityInfoForApplyRepository.java | 13 +++++++++---- .../custom/UniversityFilterRepository.java | 2 +- .../custom/UniversityFilterRepositoryImpl.java | 11 +++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java index 58fb7aeec..ad1167d52 100644 --- a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java @@ -58,8 +58,13 @@ default UniversityInfoForApply getUniversityInfoForApplyById(Long id) { .orElseThrow(() -> new CustomException(UNIVERSITY_INFO_FOR_APPLY_NOT_FOUND)); } - default UniversityInfoForApply getUniversityInfoForApplyByIdAndTerm(Long id, String term) { - return findByIdAndTerm(id, term) - .orElseThrow(() -> new CustomException(UNIVERSITY_INFO_FOR_APPLY_NOT_FOUND_FOR_TERM)); - } + @Query(""" + select distinct uia from UniversityInfoForApply uia + join fetch uia.university u + join fetch u.country c + join fetch u.region r + where uia.id in :ids +""") + List findByIdsWithUniversityAndLocation(@Param("ids") List ids); + } diff --git a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java index c35533877..ef0cd8d93 100644 --- a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java @@ -8,7 +8,7 @@ public interface UniversityFilterRepository { - List findByRegionCodeAndKeywords(String regionCode, List keywords); + List findByRegionCodeAndKeywords(String regionCode, List keywords); List findByRegionCodeAndKeywordsAndLanguageTestTypeAndTestScoreAndTerm( String regionCode, List keywords, LanguageTestType testType, String testScore, String term); diff --git a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java index 25da850da..9b3412a70 100644 --- a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java +++ b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java @@ -28,18 +28,21 @@ public UniversityFilterRepositoryImpl(EntityManager em) { } @Override - public List findByRegionCodeAndKeywords(String regionCode, List keywords) { + public List findByRegionCodeAndKeywords(String regionCode, List keywords) { QUniversity university = QUniversity.university; QCountry country = QCountry.country; QRegion region = QRegion.region; return queryFactory - .selectFrom(university) + .select(university.id) + .from(university) .join(university.country, country) .join(country.region, region) - .where(regionCodeEq(region, regionCode) - .and(countryOrUniversityContainsKeyword(country, university, keywords)) + .where( + regionCodeEq(region, regionCode) + .and(countryOrUniversityContainsKeyword(country, university, keywords)) ) + .distinct() .fetch(); } From 2abc4019faca1374cbc0f530edc6f0e35722e5d3 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 14:16:04 +0900 Subject: [PATCH 04/14] =?UTF-8?q?refactor:=20ApplicationRepository=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20-=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=203=EA=B0=9C=EB=A1=9C=20=EB=B6=84=EB=A6=AC=EB=90=98?= =?UTF-8?q?=EC=96=B4=20=EC=9E=88=EB=8A=94=20=EA=B8=B0=EC=A1=B4=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A5=BC=20=ED=95=9C=20=EB=B2=88=EC=9D=98=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ApplicationRepository.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java index 7df53eae6..97bdbf03c 100644 --- a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java @@ -20,14 +20,21 @@ public interface ApplicationRepository extends JpaRepository boolean existsByNicknameForApply(String nicknameForApply); - List findAllByFirstChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse( - UniversityInfoForApply firstChoiceUniversity, VerifyStatus verifyStatus, String term); - - List findAllBySecondChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse( - UniversityInfoForApply secondChoiceUniversity, VerifyStatus verifyStatus, String term); - - List findAllByThirdChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse( - UniversityInfoForApply thirdChoiceUniversity, VerifyStatus verifyStatus, String term); + @Query(""" + select a + from Application a + join fetch a.siteUser + where (a.firstChoiceUniversityApplyInfoId in :universityIds + or a.secondChoiceUniversityApplyInfoId in :universityIds + or a.thirdChoiceUniversityApplyInfoId in :universityIds) + and a.verifyStatus = :status + and a.term = :term + and a.isDelete = false +""") + List findApplicationsForChoices( + @Param("universityIds") List universityIds, + @Param("status") VerifyStatus status, + @Param("term") String term); @Query(""" SELECT a FROM Application a From bcb31a34f424e75ea5295b75e2c99531c63c9f19 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 14:17:20 +0900 Subject: [PATCH 05/14] =?UTF-8?q?refactor:=20ApplicationSubmissionService?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20-=20Entity=EB=B3=80=EA=B2=BD=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95.=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20=EB=A1=9C=EC=A7=81=EC=9D=80=20=EB=B3=80=ED=99=94=20?= =?UTF-8?q?=EC=97=86=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApplicationSubmissionService.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java index af1678a16..d9d78c70f 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java @@ -45,24 +45,14 @@ public class ApplicationSubmissionService { // 학점 및 어학성적이 모두 유효한 경우에만 지원서 등록이 가능하다. // 기존에 있던 status field 우선 APRROVED로 입력시킨다. @Transactional - // todo: 임시로 새로운 신청 생성 시 기존 캐싱 데이터를 삭제한다. 추후 수정 필요 - @DefaultCacheOut( - key = {"applications:all"}, - cacheManager = "customCacheManager" - ) public ApplicationSubmissionResponse apply(SiteUser siteUser, ApplyRequest applyRequest) { UniversityChoiceRequest universityChoiceRequest = applyRequest.universityChoiceRequest(); GpaScore gpaScore = getValidGpaScore(siteUser, applyRequest.gpaScoreId()); LanguageTestScore languageTestScore = getValidLanguageTestScore(siteUser, applyRequest.languageTestScoreId()); - UniversityInfoForApply firstChoiceUniversity = universityInfoForApplyRepository - .getUniversityInfoForApplyByIdAndTerm(universityChoiceRequest.firstChoiceUniversityId(), term); - UniversityInfoForApply secondChoiceUniversity = Optional.ofNullable(universityChoiceRequest.secondChoiceUniversityId()) - .map(id -> universityInfoForApplyRepository.getUniversityInfoForApplyByIdAndTerm(id, term)) - .orElse(null); - UniversityInfoForApply thirdChoiceUniversity = Optional.ofNullable(universityChoiceRequest.thirdChoiceUniversityId()) - .map(id -> universityInfoForApplyRepository.getUniversityInfoForApplyByIdAndTerm(id, term)) - .orElse(null); + Long firstChoiceUniversityId = universityChoiceRequest.firstChoiceUniversityId(); + Long secondChoiceUniversityId = universityChoiceRequest.secondChoiceUniversityId(); + Long thirdChoiceUniversityId = universityChoiceRequest.thirdChoiceUniversityId(); Optional existingApplication = applicationRepository.findBySiteUserAndTerm(siteUser, term); int updateCount = existingApplication @@ -72,10 +62,22 @@ public ApplicationSubmissionResponse apply(SiteUser siteUser, ApplyRequest apply return application.getUpdateCount() + 1; }) .orElse(1); - Application newApplication = new Application(siteUser, gpaScore.getGpa(), languageTestScore.getLanguageTest(), - term, updateCount, firstChoiceUniversity, secondChoiceUniversity, thirdChoiceUniversity, getRandomNickname()); + + Application newApplication = new Application( + siteUser, + gpaScore.getGpa(), + languageTestScore.getLanguageTest(), + term, + updateCount, + firstChoiceUniversityId, + secondChoiceUniversityId, + thirdChoiceUniversityId, + getRandomNickname() + ); + newApplication.setVerifyStatus(VerifyStatus.APPROVED); applicationRepository.save(newApplication); + return ApplicationSubmissionResponse.from(newApplication); } From d64787044e63780b2a9330f9c6056bfd36e937c4 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 14:30:54 +0900 Subject: [PATCH 06/14] =?UTF-8?q?refactor:=20ApplicationTest=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95=20-=20Entity=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20-=20?= =?UTF-8?q?=EC=A0=84=EC=9B=90=20=ED=86=B5=EA=B3=BC=20-=20ApplicationQueryS?= =?UTF-8?q?ervice=20=EB=A7=88=EC=A7=80=EB=A7=89=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9D=98=EB=8F=84?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fixture/ApplicationFixture.java | 12 +-- .../fixture/ApplicationFixtureBuilder.java | 24 ++--- .../service/ApplicationQueryServiceTest.java | 100 +++++++++++------- .../ApplicationSubmissionServiceTest.java | 18 ++-- .../integration/BaseIntegrationTest.java | 12 +-- 5 files changed, 100 insertions(+), 66 deletions(-) diff --git a/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixture.java b/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixture.java index b2cbc6460..91dc29c59 100644 --- a/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixture.java +++ b/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixture.java @@ -20,9 +20,9 @@ public class ApplicationFixture { String term, Gpa gpa, LanguageTest languageTest, - UniversityInfoForApply firstChoiceUniversity, - UniversityInfoForApply secondChoiceUniversity, - UniversityInfoForApply thirdChoiceUniversity + Long firstChoiceUniversityApplyInfoId, + Long secondChoiceUniversityApplyInfoId, + Long thirdChoiceUniversityApplyInfoId ) { return applicationFixtureBuilder.application() .siteUser(siteUser) @@ -30,9 +30,9 @@ public class ApplicationFixture { .languageTest(languageTest) .nicknameForApply(nicknameForApply) .term(term) - .firstChoiceUniversity(firstChoiceUniversity) - .secondChoiceUniversity(secondChoiceUniversity) - .thirdChoiceUniversity(thirdChoiceUniversity) + .firstChoiceUniversityApplyInfoId(firstChoiceUniversityApplyInfoId) + .secondChoiceUniversityApplyInfoId(secondChoiceUniversityApplyInfoId) + .thirdChoiceUniversityApplyInfoId(thirdChoiceUniversityApplyInfoId) .create(); } } diff --git a/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java b/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java index 5f6c06741..c9bf33c3e 100644 --- a/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java +++ b/src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java @@ -18,9 +18,9 @@ public class ApplicationFixtureBuilder { private Gpa gpa; private LanguageTest languageTest; - private UniversityInfoForApply firstChoiceUniversity; - private UniversityInfoForApply secondChoiceUniversity; - private UniversityInfoForApply thirdChoiceUniversity; + private Long firstChoiceUniversityApplyInfoId; + private Long secondChoiceUniversityApplyInfoId; + private Long thirdChoiceUniversityApplyInfoId; private SiteUser siteUser; private String nicknameForApply; private String term; @@ -39,18 +39,18 @@ public ApplicationFixtureBuilder languageTest(LanguageTest languageTest) { return this; } - public ApplicationFixtureBuilder firstChoiceUniversity(UniversityInfoForApply firstChoiceUniversity) { - this.firstChoiceUniversity = firstChoiceUniversity; + public ApplicationFixtureBuilder firstChoiceUniversityApplyInfoId(Long firstChoiceUniversityApplyInfoId) { + this.firstChoiceUniversityApplyInfoId = firstChoiceUniversityApplyInfoId; return this; } - public ApplicationFixtureBuilder secondChoiceUniversity(UniversityInfoForApply secondChoiceUniversity) { - this.secondChoiceUniversity = secondChoiceUniversity; + public ApplicationFixtureBuilder secondChoiceUniversityApplyInfoId(Long secondChoiceUniversityApplyInfoId) { + this.secondChoiceUniversityApplyInfoId = secondChoiceUniversityApplyInfoId; return this; } - public ApplicationFixtureBuilder thirdChoiceUniversity(UniversityInfoForApply thirdChoiceUniversity) { - this.thirdChoiceUniversity = thirdChoiceUniversity; + public ApplicationFixtureBuilder thirdChoiceUniversityApplyInfoId(Long thirdChoiceUniversityApplyInfoId) { + this.thirdChoiceUniversityApplyInfoId = thirdChoiceUniversityApplyInfoId; return this; } @@ -75,9 +75,9 @@ public Application create() { gpa, languageTest, term, - firstChoiceUniversity, - secondChoiceUniversity, - thirdChoiceUniversity, + firstChoiceUniversityApplyInfoId, + secondChoiceUniversityApplyInfoId, + thirdChoiceUniversityApplyInfoId, nicknameForApply ); application.setVerifyStatus(VerifyStatus.APPROVED); diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java index ac0b83619..4bad0fc9d 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java @@ -70,6 +70,11 @@ class ApplicationQueryServiceTest { private LanguageTestScore languageTestScore1; private LanguageTestScore languageTestScore2; private LanguageTestScore languageTestScore3; + + private Long firstChoiceUniversityApplyInfoId = 1L; + private Long secondChoiceUniversityApplyInfoId = 2L; + + private Long thirdChoiceUniversityApplyInfoId = 3L; private UniversityInfoForApply 괌대학_A_지원_정보; private UniversityInfoForApply 괌대학_B_지원_정보; @@ -106,7 +111,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -116,7 +121,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - 괌대학_B_지원_정보, + secondChoiceUniversityApplyInfoId, null, null ); @@ -126,7 +131,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - 서던덴마크대학교_지원_정보, + thirdChoiceUniversityApplyInfoId, null, null ); @@ -158,7 +163,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -168,7 +173,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - 괌대학_B_지원_정보, + secondChoiceUniversityApplyInfoId, null, null ); @@ -178,7 +183,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - 서던덴마크대학교_지원_정보, + thirdChoiceUniversityApplyInfoId, null, null ); @@ -208,7 +213,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -218,7 +223,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - 괌대학_B_지원_정보, + secondChoiceUniversityApplyInfoId, null, null ); @@ -228,7 +233,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - 서던덴마크대학교_지원_정보, + thirdChoiceUniversityApplyInfoId, null, null ); @@ -258,7 +263,7 @@ class 지원자_목록_조회_테스트 { "1988-1", gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -286,7 +291,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -298,7 +303,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_B_지원_정보, + secondChoiceUniversityApplyInfoId, null, null ); @@ -330,7 +335,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -340,7 +345,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - 괌대학_A_지원_정보, + firstChoiceUniversityApplyInfoId, null, null ); @@ -350,7 +355,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - 괌대학_B_지원_정보, + thirdChoiceUniversityApplyInfoId, null, null ); @@ -375,47 +380,70 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - 괌대학_A_지원_정보, - null, - null + firstChoiceUniversityApplyInfoId, + secondChoiceUniversityApplyInfoId, + thirdChoiceUniversityApplyInfoId ); - applicationFixture.지원서( + Application application2 = applicationFixture.지원서( user2, "nickname2", term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - null, - 괌대학_B_지원_정보, + firstChoiceUniversityApplyInfoId, + secondChoiceUniversityApplyInfoId, null ); - applicationFixture.지원서( + Application application3 = applicationFixture.지원서( user3, "nickname3", term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), + firstChoiceUniversityApplyInfoId, null, - null, - 서던덴마크대학교_지원_정보 + null ); // when ApplicationsResponse response = applicationQueryService.getApplicantsByUserApplications(user1); // then - assertThat(response.firstChoice()).containsExactlyInAnyOrder( - UniversityApplicantsResponse.of(괌대학_A_지원_정보, - List.of(ApplicantResponse.of(application1, true))) - ); - - assertThat(response.secondChoice()).containsExactlyInAnyOrder( - UniversityApplicantsResponse.of(괌대학_A_지원_정보, List.of()) - ); - - assertThat(response.thirdChoice()).containsExactlyInAnyOrder( - UniversityApplicantsResponse.of(괌대학_A_지원_정보, List.of()) - ); + assertThat(response.firstChoice()) + .filteredOn(uar -> !uar.applicants().isEmpty()) + .containsExactly( + UniversityApplicantsResponse.of( + universityInfoForApplyFixture.괌대학_A_지원_정보(), + List.of( + ApplicantResponse.of(application1, true), + ApplicantResponse.of(application2, false), + ApplicantResponse.of(application3, false) + ) + ) + ); + + assertThat(response.secondChoice()) + .filteredOn(uar -> !uar.applicants().isEmpty()) + .containsExactly( + UniversityApplicantsResponse.of( + universityInfoForApplyFixture.괌대학_B_지원_정보(), + List.of( + ApplicantResponse.of(application1, true), + ApplicantResponse.of(application2, false) + ) + ) + ); + + assertThat(response.thirdChoice()) + .filteredOn(uar -> !uar.applicants().isEmpty()) + .containsExactly( + UniversityApplicantsResponse.of( + universityInfoForApplyFixture.서던덴마크대학교_지원_정보(), + List.of( + ApplicantResponse.of(application1, true) + ) + ) + ); } } } diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java index f70cd9fc0..e57c77d58 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java @@ -86,12 +86,18 @@ void setUp() { // then Application savedApplication = applicationRepository.findBySiteUserAndTerm(user, term).orElseThrow(); assertAll( - () -> assertThat(response.applyCount()).isEqualTo(savedApplication.getUpdateCount()), - () -> assertThat(savedApplication.getVerifyStatus()).isEqualTo(VerifyStatus.APPROVED), - () -> assertThat(savedApplication.isDelete()).isFalse(), - () -> assertThat(savedApplication.getFirstChoiceUniversity().getId()).isEqualTo(괌대학_A_지원_정보.getId()), - () -> assertThat(savedApplication.getSecondChoiceUniversity().getId()).isEqualTo(괌대학_B_지원_정보.getId()), - () -> assertThat(savedApplication.getThirdChoiceUniversity().getId()).isEqualTo(서던덴마크대학교_지원_정보.getId()) + () -> assertThat(response.applyCount()) + .isEqualTo(savedApplication.getUpdateCount()), + () -> assertThat(savedApplication.getVerifyStatus()) + .isEqualTo(VerifyStatus.APPROVED), + () -> assertThat(savedApplication.isDelete()) + .isFalse(), + () -> assertThat(savedApplication.getFirstChoiceUniversityApplyInfoId()) + .isEqualTo(괌대학_A_지원_정보.getId()), + () -> assertThat(savedApplication.getSecondChoiceUniversityApplyInfoId()) + .isEqualTo(괌대학_B_지원_정보.getId()), + () -> assertThat(savedApplication.getThirdChoiceUniversityApplyInfoId()) + .isEqualTo(서던덴마크대학교_지원_정보.getId()) ); } diff --git a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java index ae449641f..04b2647ae 100644 --- a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java +++ b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java @@ -424,25 +424,25 @@ private void setUpLanguageRequirements() { private void setUpApplications() { 테스트유저_2_괌대학_B_괌대학_A_린츠_카톨릭대학_지원서 = new Application(테스트유저_2, createApprovedGpaScore(테스트유저_2).getGpa(), createApprovedLanguageTestScore(테스트유저_2).getLanguageTest(), - term, 괌대학_B_지원_정보, 괌대학_A_지원_정보, 린츠_카톨릭대학_지원_정보, "user2_nickname"); + term, 2L, 1L, 15L, "user2_nickname"); 테스트유저_3_괌대학_A_괌대학_B_그라츠공과대학_지원서 = new Application(테스트유저_3, createApprovedGpaScore(테스트유저_3).getGpa(), createApprovedLanguageTestScore(테스트유저_3).getLanguageTest(), - term, 괌대학_A_지원_정보, 괌대학_B_지원_정보, 그라츠공과대학_지원_정보, "user3_nickname"); + term, 1L, 2L, 14L, "user3_nickname"); 테스트유저_4_메이지대학_그라츠대학_서던덴마크대학_지원서 = new Application(테스트유저_4, createApprovedGpaScore(테스트유저_4).getGpa(), createApprovedLanguageTestScore(테스트유저_4).getLanguageTest(), - term, 메이지대학_지원_정보, 그라츠대학_지원_정보, 서던덴마크대학교_지원_정보, "user4_nickname"); + term, 18L, 13L, 9L, "user4_nickname"); 테스트유저_5_네바다주립대학_그라츠공과대학_메이지대학_지원서 = new Application(테스트유저_5, createApprovedGpaScore(테스트유저_5).getGpa(), createApprovedLanguageTestScore(테스트유저_5).getLanguageTest(), - term, 네바다주립대학_라스베이거스_지원_정보, 그라츠공과대학_지원_정보, 메이지대학_지원_정보, "user5_nickname"); + term, 3L, 14L, 18L, "user5_nickname"); 테스트유저_6_X_X_X_지원서 = new Application(테스트유저_6, createApprovedGpaScore(테스트유저_6).getGpa(), createApprovedLanguageTestScore(테스트유저_6).getLanguageTest(), term, null, null, null, "user6_nickname"); 테스트유저_7_코펜하겐IT대학_X_X_지원서 = new Application(테스트유저_7, createApprovedGpaScore(테스트유저_7).getGpa(), createApprovedLanguageTestScore(테스트유저_7).getLanguageTest(), - term, 코펜하겐IT대학_지원_정보, null, null, "user7_nickname"); + term, 10L, null, null, "user7_nickname"); 이전학기_지원서 = new Application(이전학기_지원자, createApprovedGpaScore(이전학기_지원자).getGpa(), createApprovedLanguageTestScore(이전학기_지원자).getLanguageTest(), - "1988-1", 네바다주립대학_라스베이거스_지원_정보, 그라츠공과대학_지원_정보, 메이지대학_지원_정보, "old_nickname"); + "1988-1", 3L, 14L, 18L, "old_nickname"); 테스트유저_2_괌대학_B_괌대학_A_린츠_카톨릭대학_지원서.setVerifyStatus(VerifyStatus.APPROVED); 테스트유저_3_괌대학_A_괌대학_B_그라츠공과대학_지원서.setVerifyStatus(VerifyStatus.APPROVED); From b6cf6e9df31d6cddb926b0b775eaf9e55b67382a Mon Sep 17 00:00:00 2001 From: Yeonri Date: Sat, 24 May 2025 15:37:52 +0900 Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20ApplicationTest=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95=20-=20UniversityInfoForApplyId?= =?UTF-8?q?=20=ED=95=98=EB=93=9C=EC=BD=94=EB=94=A9=20=EB=90=98=EC=96=B4?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=86=B5=EA=B3=BC=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApplicationQueryServiceTest.java | 18 ++-- .../integration/BaseIntegrationTest.java | 84 +++++++++++++++---- 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java index 4bad0fc9d..6ad501c2e 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java @@ -70,11 +70,11 @@ class ApplicationQueryServiceTest { private LanguageTestScore languageTestScore1; private LanguageTestScore languageTestScore2; private LanguageTestScore languageTestScore3; - - private Long firstChoiceUniversityApplyInfoId = 1L; - private Long secondChoiceUniversityApplyInfoId = 2L; - - private Long thirdChoiceUniversityApplyInfoId = 3L; + + private Long firstChoiceUniversityApplyInfoId; + private Long secondChoiceUniversityApplyInfoId; + private Long thirdChoiceUniversityApplyInfoId; + private UniversityInfoForApply 괌대학_A_지원_정보; private UniversityInfoForApply 괌대학_B_지원_정보; @@ -94,9 +94,13 @@ void setUp() { gpaScore3 = gpaScoreFixture.GPA_점수(VerifyStatus.APPROVED, user3); languageTestScore3 = languageTestScoreFixture.어학_점수(VerifyStatus.APPROVED, user3); - 괌대학_A_지원_정보 = universityInfoForApplyFixture.괌대학_A_지원_정보(); - 괌대학_B_지원_정보 = universityInfoForApplyFixture.괌대학_B_지원_정보(); + 괌대학_A_지원_정보 = universityInfoForApplyFixture.괌대학_A_지원_정보(); + 괌대학_B_지원_정보 = universityInfoForApplyFixture.괌대학_B_지원_정보(); 서던덴마크대학교_지원_정보 = universityInfoForApplyFixture.서던덴마크대학교_지원_정보(); + + firstChoiceUniversityApplyInfoId = 괌대학_A_지원_정보.getId(); + secondChoiceUniversityApplyInfoId = 괌대학_B_지원_정보.getId(); + thirdChoiceUniversityApplyInfoId = 서던덴마크대학교_지원_정보.getId(); } @Nested diff --git a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java index 04b2647ae..b51c18906 100644 --- a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java +++ b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java @@ -423,26 +423,82 @@ private void setUpLanguageRequirements() { } private void setUpApplications() { - 테스트유저_2_괌대학_B_괌대학_A_린츠_카톨릭대학_지원서 = new Application(테스트유저_2, createApprovedGpaScore(테스트유저_2).getGpa(), createApprovedLanguageTestScore(테스트유저_2).getLanguageTest(), - term, 2L, 1L, 15L, "user2_nickname"); + 테스트유저_2_괌대학_B_괌대학_A_린츠_카톨릭대학_지원서 = new Application( + 테스트유저_2, + createApprovedGpaScore(테스트유저_2).getGpa(), + createApprovedLanguageTestScore(테스트유저_2).getLanguageTest(), + term, + 괌대학_B_지원_정보.getId(), + 괌대학_A_지원_정보.getId(), + 린츠_카톨릭대학_지원_정보.getId(), + "user2_nickname" + ); - 테스트유저_3_괌대학_A_괌대학_B_그라츠공과대학_지원서 = new Application(테스트유저_3, createApprovedGpaScore(테스트유저_3).getGpa(), createApprovedLanguageTestScore(테스트유저_3).getLanguageTest(), - term, 1L, 2L, 14L, "user3_nickname"); + 테스트유저_3_괌대학_A_괌대학_B_그라츠공과대학_지원서 = new Application( + 테스트유저_3, + createApprovedGpaScore(테스트유저_3).getGpa(), + createApprovedLanguageTestScore(테스트유저_3).getLanguageTest(), + term, + 괌대학_A_지원_정보.getId(), + 괌대학_B_지원_정보.getId(), + 그라츠공과대학_지원_정보.getId(), + "user3_nickname" + ); - 테스트유저_4_메이지대학_그라츠대학_서던덴마크대학_지원서 = new Application(테스트유저_4, createApprovedGpaScore(테스트유저_4).getGpa(), createApprovedLanguageTestScore(테스트유저_4).getLanguageTest(), - term, 18L, 13L, 9L, "user4_nickname"); + 테스트유저_4_메이지대학_그라츠대학_서던덴마크대학_지원서 = new Application( + 테스트유저_4, + createApprovedGpaScore(테스트유저_4).getGpa(), + createApprovedLanguageTestScore(테스트유저_4).getLanguageTest(), + term, + 메이지대학_지원_정보.getId(), + 그라츠대학_지원_정보.getId(), + 서던덴마크대학교_지원_정보.getId(), + "user4_nickname" + ); - 테스트유저_5_네바다주립대학_그라츠공과대학_메이지대학_지원서 = new Application(테스트유저_5, createApprovedGpaScore(테스트유저_5).getGpa(), createApprovedLanguageTestScore(테스트유저_5).getLanguageTest(), - term, 3L, 14L, 18L, "user5_nickname"); + 테스트유저_5_네바다주립대학_그라츠공과대학_메이지대학_지원서 = new Application( + 테스트유저_5, + createApprovedGpaScore(테스트유저_5).getGpa(), + createApprovedLanguageTestScore(테스트유저_5).getLanguageTest(), + term, + 네바다주립대학_라스베이거스_지원_정보.getId(), + 그라츠공과대학_지원_정보.getId(), + 메이지대학_지원_정보.getId(), + "user5_nickname" + ); - 테스트유저_6_X_X_X_지원서 = new Application(테스트유저_6, createApprovedGpaScore(테스트유저_6).getGpa(), createApprovedLanguageTestScore(테스트유저_6).getLanguageTest(), - term, null, null, null, "user6_nickname"); + 테스트유저_6_X_X_X_지원서 = new Application( + 테스트유저_6, + createApprovedGpaScore(테스트유저_6).getGpa(), + createApprovedLanguageTestScore(테스트유저_6).getLanguageTest(), + term, + null, + null, + null, + "user6_nickname" + ); - 테스트유저_7_코펜하겐IT대학_X_X_지원서 = new Application(테스트유저_7, createApprovedGpaScore(테스트유저_7).getGpa(), createApprovedLanguageTestScore(테스트유저_7).getLanguageTest(), - term, 10L, null, null, "user7_nickname"); + 테스트유저_7_코펜하겐IT대학_X_X_지원서 = new Application( + 테스트유저_7, + createApprovedGpaScore(테스트유저_7).getGpa(), + createApprovedLanguageTestScore(테스트유저_7).getLanguageTest(), + term, + 코펜하겐IT대학_지원_정보.getId(), + null, + null, + "user7_nickname" + ); - 이전학기_지원서 = new Application(이전학기_지원자, createApprovedGpaScore(이전학기_지원자).getGpa(), createApprovedLanguageTestScore(이전학기_지원자).getLanguageTest(), - "1988-1", 3L, 14L, 18L, "old_nickname"); + 이전학기_지원서 = new Application( + 이전학기_지원자, + createApprovedGpaScore(이전학기_지원자).getGpa(), + createApprovedLanguageTestScore(이전학기_지원자).getLanguageTest(), + "1988-1", + 네바다주립대학_라스베이거스_지원_정보.getId(), + 그라츠공과대학_지원_정보.getId(), + 메이지대학_지원_정보.getId(), + "old_nickname" + ); 테스트유저_2_괌대학_B_괌대학_A_린츠_카톨릭대학_지원서.setVerifyStatus(VerifyStatus.APPROVED); 테스트유저_3_괌대학_A_괌대학_B_그라츠공과대학_지원서.setVerifyStatus(VerifyStatus.APPROVED); From 6465be009d8dd832ed07e2139e24355a6ca6ffa6 Mon Sep 17 00:00:00 2001 From: lsy1307 Date: Mon, 26 May 2025 16:41:08 +0900 Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EC=99=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EB=A6=AC=EB=B7=B0=20=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20-=20=EC=BD=94=EB=93=9C=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=A4=EC=85=98=20=ED=86=B5=EC=9D=BC=20-=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=9D=B4=ED=95=B4=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=89=BD=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20-=20Applicat?= =?UTF-8?q?ion=20Repository=20universityId=EA=B8=B0=EB=B0=98=EA=B3=BC=20ui?= =?UTF-8?q?aId=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/domain/Application.java | 2 +- .../repository/ApplicationRepository.java | 36 ++++---- .../service/ApplicationQueryService.java | 90 ++++++++++--------- .../UniversityInfoForApplyRepository.java | 33 +++++-- .../UniversityFilterRepositoryImpl.java | 1 - 5 files changed, 91 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/domain/Application.java b/src/main/java/com/example/solidconnection/application/domain/Application.java index b4b62fb15..bad219978 100644 --- a/src/main/java/com/example/solidconnection/application/domain/Application.java +++ b/src/main/java/com/example/solidconnection/application/domain/Application.java @@ -53,7 +53,7 @@ public class Application { @Column private boolean isDelete = false; - @Column + @Column(nullable = false) private Long firstChoiceUniversityApplyInfoId; @Column diff --git a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java index 97bdbf03c..27143ec8d 100644 --- a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java @@ -21,27 +21,25 @@ public interface ApplicationRepository extends JpaRepository boolean existsByNicknameForApply(String nicknameForApply); @Query(""" - select a - from Application a - join fetch a.siteUser - where (a.firstChoiceUniversityApplyInfoId in :universityIds - or a.secondChoiceUniversityApplyInfoId in :universityIds - or a.thirdChoiceUniversityApplyInfoId in :universityIds) - and a.verifyStatus = :status - and a.term = :term - and a.isDelete = false -""") - List findApplicationsForChoices( - @Param("universityIds") List universityIds, - @Param("status") VerifyStatus status, - @Param("term") String term); + SELECT a + FROM Application a + JOIN FETCH a.siteUser + WHERE (a.firstChoiceUniversityApplyInfoId IN :universityIds + OR a.secondChoiceUniversityApplyInfoId IN :universityIds + OR a.thirdChoiceUniversityApplyInfoId IN :universityIds) + AND a.verifyStatus = :status + AND a.term = :term + AND a.isDelete = false + """) + List findApplicationsByUniversityChoices(@Param("universityIds") List universityIds, @Param("status") VerifyStatus status, @Param("term") String term); @Query(""" - SELECT a FROM Application a - WHERE a.siteUser = :siteUser - AND a.term = :term - AND a.isDelete = false - """) + SELECT a + FROM Application a + WHERE a.siteUser = :siteUser + AND a.term = :term + AND a.isDelete = false + """) Optional findBySiteUserAndTerm(@Param("siteUser") SiteUser siteUser, @Param("term") String term); default Application getApplicationBySiteUserAndTerm(SiteUser siteUser, String term) { diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java index 60eb8659d..ff0f132ff 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java @@ -16,9 +16,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.List; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; import static com.example.solidconnection.common.exception.ErrorCode.APPLICATION_NOT_APPROVED; @@ -33,27 +38,30 @@ public class ApplicationQueryService { @Value("${university.term}") public String term; + // todo: 캐싱 정책 변경 시 수정 필요 @Transactional(readOnly = true) public ApplicationsResponse getApplicants(SiteUser siteUser, String regionCode, String keyword) { // 1. 대학 ID 필터링 (regionCode, keyword) List universityIds = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); - if (universityIds.isEmpty()) return new ApplicationsResponse(List.of(), List.of(), List.of()); + if (universityIds.isEmpty()) { + return new ApplicationsResponse(List.of(), List.of(), List.of()); + } // 2. 조건에 맞는 모든 Application 한 번에 조회 - List applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); + List applications = applicationRepository.findApplicationsByUniversityChoices(universityIds, VerifyStatus.APPROVED, term); // 3. 대학정보 조회 - List universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); + List universityInfosForApply = universityInfoForApplyRepository.findByUniversityIdsWithUniversityAndLocation(universityIds); // 4. 지원서 분류 및 DTO 변환 - return classifyApplicationsByChoice(universityInfos, applications, siteUser); + return classifyApplicationsByChoice(universityInfosForApply, applications, siteUser); } @Transactional(readOnly = true) public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { Application userLatestApplication = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term); - List universityIds = Stream.of( + List universityInfoForApplyIds = Stream.of( userLatestApplication.getFirstChoiceUniversityApplyInfoId(), userLatestApplication.getSecondChoiceUniversityApplyInfoId(), userLatestApplication.getThirdChoiceUniversityApplyInfoId() @@ -61,62 +69,60 @@ public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { .filter(Objects::nonNull) .collect(Collectors.toList()); - if (universityIds.isEmpty()) { + if (universityInfoForApplyIds.isEmpty()) { return new ApplicationsResponse(List.of(), List.of(), List.of()); } - List applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); - List universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); + List applications = applicationRepository.findApplicationsByUniversityChoices(universityInfoForApplyIds, VerifyStatus.APPROVED, term); + List universityInfosForApply = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityInfoForApplyIds); - return classifyApplicationsByChoice(universityInfos, applications, siteUser); + return classifyApplicationsByChoice(universityInfosForApply, applications, siteUser); } private ApplicationsResponse classifyApplicationsByChoice( - List universityInfos, + List universityInfosForApply, List applications, SiteUser siteUser) { + Map> firstChoiceMap = createChoiceMap(applications, Application::getFirstChoiceUniversityApplyInfoId); + Map> secondChoiceMap = createChoiceMap(applications, Application::getSecondChoiceUniversityApplyInfoId); + Map> thirdChoiceMap = createChoiceMap(applications, Application::getThirdChoiceUniversityApplyInfoId); - Map> firstChoiceMap = new HashMap<>(); - Map> secondChoiceMap = new HashMap<>(); - Map> thirdChoiceMap = new HashMap<>(); + List firstChoiceApplicants = + createUniversityApplicantsResponses(universityInfosForApply, firstChoiceMap, siteUser); + List secondChoiceApplicants = + createUniversityApplicantsResponses(universityInfosForApply, secondChoiceMap, siteUser); + List thirdChoiceApplicants = + createUniversityApplicantsResponses(universityInfosForApply, thirdChoiceMap, siteUser); - for (Application a : applications) { - if (a.getFirstChoiceUniversityApplyInfoId() != null) { - firstChoiceMap.computeIfAbsent(a.getFirstChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); - } - if (a.getSecondChoiceUniversityApplyInfoId() != null) { - secondChoiceMap.computeIfAbsent(a.getSecondChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); - } - if (a.getThirdChoiceUniversityApplyInfoId() != null) { - thirdChoiceMap.computeIfAbsent(a.getThirdChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); + return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); + } + + private Map> createChoiceMap( + List applications, + Function choiceIdExtractor) { + Map> choiceMap = new HashMap<>(); + + for (Application application : applications) { + Long choiceId = choiceIdExtractor.apply(application); + if (choiceId != null) { + choiceMap.computeIfAbsent(choiceId, k -> new ArrayList<>()).add(application); } } - List firstChoiceApplicants = universityInfos.stream() - .map(uia -> UniversityApplicantsResponse.of( - uia, - firstChoiceMap.getOrDefault(uia.getId(), List.of()).stream() - .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) - .toList())) - .toList(); - - List secondChoiceApplicants = universityInfos.stream() - .map(uia -> UniversityApplicantsResponse.of( - uia, - secondChoiceMap.getOrDefault(uia.getId(), List.of()).stream() - .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) - .toList())) - .toList(); + return choiceMap; + } - List thirdChoiceApplicants = universityInfos.stream() + private List createUniversityApplicantsResponses( + List universityInfosForApply, + Map> choiceMap, + SiteUser siteUser) { + return universityInfosForApply.stream() .map(uia -> UniversityApplicantsResponse.of( uia, - thirdChoiceMap.getOrDefault(uia.getId(), List.of()).stream() + choiceMap.getOrDefault(uia.getId(), List.of()).stream() .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) .toList())) .toList(); - - return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); } @Transactional(readOnly = true) diff --git a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java index ad1167d52..6e21abdd4 100644 --- a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java @@ -22,7 +22,12 @@ public interface UniversityInfoForApplyRepository extends JpaRepository findFirstByKoreanNameAndTerm(String koreanName, String term); - @Query("SELECT c FROM UniversityInfoForApply c WHERE c.university IN :universities AND c.term = :term") + @Query(""" + SELECT uifa + FROM UniversityInfoForApply uifa + WHERE uifa.university IN :universities + AND uifa.term = :term + """) List findByUniversitiesAndTerm(@Param("universities") List universities, @Param("term") String term); @Query(""" @@ -49,7 +54,8 @@ OR u.region.code IN ( SELECT * FROM university_info_for_apply WHERE term = :term - ORDER BY RAND() LIMIT :limitNum + ORDER BY RAND() + LIMIT :limitNum """, nativeQuery = true) List findRandomByTerm(@Param("term") String term, @Param("limitNum") int limitNum); @@ -59,12 +65,23 @@ default UniversityInfoForApply getUniversityInfoForApplyById(Long id) { } @Query(""" - select distinct uia from UniversityInfoForApply uia - join fetch uia.university u - join fetch u.country c - join fetch u.region r - where uia.id in :ids -""") + SELECT DISTINCT uifa + FROM UniversityInfoForApply uifa + JOIN FETCH uifa.university u + JOIN FETCH u.country c + JOIN FETCH u.region r + WHERE uifa.id IN :ids + """) List findByIdsWithUniversityAndLocation(@Param("ids") List ids); + @Query(""" + SELECT DISTINCT uifa + FROM UniversityInfoForApply uifa + JOIN FETCH uifa.university u + JOIN FETCH u.country c + JOIN FETCH u.region r + WHERE u.id IN :universityIds + """) + List findByUniversityIdsWithUniversityAndLocation(@Param("universityIds") List universityIds); + } diff --git a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java index 9b3412a70..e66c5454a 100644 --- a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java +++ b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java @@ -72,7 +72,6 @@ private BooleanExpression createKeywordCondition(StringPath namePath, List findByRegionCodeAndKeywordsAndLanguageTestTypeAndTestScoreAndTerm( String regionCode, List keywords, LanguageTestType testType, String testScore, String term) { - QUniversity university = QUniversity.university; QCountry country = QCountry.country; QRegion region = QRegion.region; From f140a3badc322462f37693bbf71744038666b1d0 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 26 May 2025 17:51:46 +0900 Subject: [PATCH 09/14] =?UTF-8?q?refactor:=20ApplicationTest=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95=20-=20=EB=A7=88=EC=A7=80?= =?UTF-8?q?=EB=A7=89=20=EB=A9=94=EC=84=9C=EB=93=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=98=EB=8F=84=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EC=BB=A8=EB=B2=A4=EC=85=98=EC=97=90?= =?UTF-8?q?=20=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95=20-=20BaseIntegratio?= =?UTF-8?q?nTest=EC=97=90=EC=84=9C=20firstUIAId=EC=97=90=20null=EA=B0=92?= =?UTF-8?q?=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApplicationQueryServiceTest.java | 97 ++++++------------- .../integration/BaseIntegrationTest.java | 2 +- 2 files changed, 32 insertions(+), 67 deletions(-) diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java index 6ad501c2e..d95b89e26 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java @@ -71,10 +71,6 @@ class ApplicationQueryServiceTest { private LanguageTestScore languageTestScore2; private LanguageTestScore languageTestScore3; - private Long firstChoiceUniversityApplyInfoId; - private Long secondChoiceUniversityApplyInfoId; - private Long thirdChoiceUniversityApplyInfoId; - private UniversityInfoForApply 괌대학_A_지원_정보; private UniversityInfoForApply 괌대학_B_지원_정보; @@ -94,13 +90,9 @@ void setUp() { gpaScore3 = gpaScoreFixture.GPA_점수(VerifyStatus.APPROVED, user3); languageTestScore3 = languageTestScoreFixture.어학_점수(VerifyStatus.APPROVED, user3); - 괌대학_A_지원_정보 = universityInfoForApplyFixture.괌대학_A_지원_정보(); - 괌대학_B_지원_정보 = universityInfoForApplyFixture.괌대학_B_지원_정보(); + 괌대학_A_지원_정보 = universityInfoForApplyFixture.괌대학_A_지원_정보(); + 괌대학_B_지원_정보 = universityInfoForApplyFixture.괌대학_B_지원_정보(); 서던덴마크대학교_지원_정보 = universityInfoForApplyFixture.서던덴마크대학교_지원_정보(); - - firstChoiceUniversityApplyInfoId = 괌대학_A_지원_정보.getId(); - secondChoiceUniversityApplyInfoId = 괌대학_B_지원_정보.getId(); - thirdChoiceUniversityApplyInfoId = 서던덴마크대학교_지원_정보.getId(); } @Nested @@ -115,7 +107,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -125,7 +117,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - secondChoiceUniversityApplyInfoId, + 괌대학_B_지원_정보.getId(), null, null ); @@ -135,7 +127,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - thirdChoiceUniversityApplyInfoId, + 서던덴마크대학교_지원_정보.getId(), null, null ); @@ -167,7 +159,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -177,7 +169,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - secondChoiceUniversityApplyInfoId, + 괌대학_B_지원_정보.getId(), null, null ); @@ -187,7 +179,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - thirdChoiceUniversityApplyInfoId, + 서던덴마크대학교_지원_정보.getId(), null, null ); @@ -217,7 +209,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -227,7 +219,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - secondChoiceUniversityApplyInfoId, + 괌대학_B_지원_정보.getId(), null, null ); @@ -237,7 +229,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - thirdChoiceUniversityApplyInfoId, + 서던덴마크대학교_지원_정보.getId(), null, null ); @@ -267,7 +259,7 @@ class 지원자_목록_조회_테스트 { "1988-1", gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -295,7 +287,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -307,7 +299,7 @@ class 지원자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - secondChoiceUniversityApplyInfoId, + 괌대학_B_지원_정보.getId(), null, null ); @@ -339,7 +331,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -349,7 +341,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 괌대학_A_지원_정보.getId(), null, null ); @@ -359,7 +351,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - thirdChoiceUniversityApplyInfoId, + 서던덴마크대학교_지원_정보.getId(), null, null ); @@ -384,9 +376,9 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore1.getGpa(), languageTestScore1.getLanguageTest(), - firstChoiceUniversityApplyInfoId, - secondChoiceUniversityApplyInfoId, - thirdChoiceUniversityApplyInfoId + 괌대학_A_지원_정보.getId(), + null, + null ); Application application2 = applicationFixture.지원서( user2, @@ -394,9 +386,9 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore2.getGpa(), languageTestScore2.getLanguageTest(), - firstChoiceUniversityApplyInfoId, - secondChoiceUniversityApplyInfoId, - null + 괌대학_A_지원_정보.getId(), + 괌대학_B_지원_정보.getId(), + 서던덴마크대학교_지원_정보.getId() ); Application application3 = applicationFixture.지원서( user3, @@ -404,7 +396,7 @@ class 경쟁자_목록_조회_테스트 { term, gpaScore3.getGpa(), languageTestScore3.getLanguageTest(), - firstChoiceUniversityApplyInfoId, + 서던덴마크대학교_지원_정보.getId(), null, null ); @@ -414,40 +406,13 @@ class 경쟁자_목록_조회_테스트 { // then assertThat(response.firstChoice()) - .filteredOn(uar -> !uar.applicants().isEmpty()) - .containsExactly( - UniversityApplicantsResponse.of( - universityInfoForApplyFixture.괌대학_A_지원_정보(), - List.of( - ApplicantResponse.of(application1, true), - ApplicantResponse.of(application2, false), - ApplicantResponse.of(application3, false) - ) - ) - ); - - assertThat(response.secondChoice()) - .filteredOn(uar -> !uar.applicants().isEmpty()) - .containsExactly( - UniversityApplicantsResponse.of( - universityInfoForApplyFixture.괌대학_B_지원_정보(), - List.of( - ApplicantResponse.of(application1, true), - ApplicantResponse.of(application2, false) - ) - ) - ); - - assertThat(response.thirdChoice()) - .filteredOn(uar -> !uar.applicants().isEmpty()) - .containsExactly( - UniversityApplicantsResponse.of( - universityInfoForApplyFixture.서던덴마크대학교_지원_정보(), - List.of( - ApplicantResponse.of(application1, true) - ) - ) - ); + .hasSize(1) + .allSatisfy(uar -> { + assertThat(uar.koreanName()).isEqualTo(괌대학_A_지원_정보.getKoreanName()); + assertThat(uar.applicants()) + .extracting(ApplicantResponse::nicknameForApply) + .containsExactlyInAnyOrder("nickname1", "nickname2"); + }); } } } diff --git a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java index b51c18906..dabd813eb 100644 --- a/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java +++ b/src/test/java/com/example/solidconnection/support/integration/BaseIntegrationTest.java @@ -472,7 +472,7 @@ private void setUpApplications() { createApprovedGpaScore(테스트유저_6).getGpa(), createApprovedLanguageTestScore(테스트유저_6).getLanguageTest(), term, - null, + 그라츠대학_지원_정보.getId(), null, null, "user6_nickname" From ea0c1f3f0fa039d5d7bde038a201bb90d456bfe7 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 26 May 2025 22:49:19 +0900 Subject: [PATCH 10/14] =?UTF-8?q?refactor:=20Application=20Entity=20Index?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20=EC=A1=B0=ED=9A=8C=20=EC=84=B1?= =?UTF-8?q?=EB=8A=A5=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?Application=20Entity=20Index=EC=B6=94=EA=B0=80=20-=20Applicatio?= =?UTF-8?q?n=20Repository=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EA=B3=B5=EB=B0=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/domain/Application.java | 28 +++++++++++++------ .../repository/ApplicationRepository.java | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/domain/Application.java b/src/main/java/com/example/solidconnection/application/domain/Application.java index bad219978..9bdbbdb3c 100644 --- a/src/main/java/com/example/solidconnection/application/domain/Application.java +++ b/src/main/java/com/example/solidconnection/application/domain/Application.java @@ -10,7 +10,9 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.Index; import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -24,6 +26,16 @@ @DynamicUpdate @DynamicInsert @Entity +@Table(indexes = { + @Index(name = "idx_app_user_term_delete", + columnList = "site_user_id, term, is_delete"), + @Index(name = "idx_app_first_choice_search", + columnList = "verify_status, term, is_delete, first_choice_university_apply_info_id"), + @Index(name = "idx_app_second_choice_search", + columnList = "verify_status, term, is_delete, second_choice_university_apply_info_id"), + @Index(name = "idx_app_third_choice_search", + columnList = "verify_status, term, is_delete, third_choice_university_apply_info_id") +}) public class Application { @Id @@ -37,29 +49,29 @@ public class Application { private LanguageTest languageTest; @Setter - @Column(columnDefinition = "varchar(50) not null default 'PENDING'") + @Column(columnDefinition = "varchar(50) not null default 'PENDING'", name="verify_status") @Enumerated(EnumType.STRING) private VerifyStatus verifyStatus; - @Column(length = 100) + @Column(length = 100, name="nickname_for_apply") private String nicknameForApply; - @Column(columnDefinition = "int not null default 1") + @Column(columnDefinition = "int not null default 1", name="update_count") private Integer updateCount; - @Column(length = 50, nullable = false) + @Column(length = 50, nullable = false, name="term") private String term; - @Column + @Column(name="is_delete") private boolean isDelete = false; - @Column(nullable = false) + @Column(nullable = false, name="first_choice_university_apply_info_id") private Long firstChoiceUniversityApplyInfoId; - @Column + @Column(name="second_choice_university_apply_info_id") private Long secondChoiceUniversityApplyInfoId; - @Column + @Column(name="third_choice_university_apply_info_id") private Long thirdChoiceUniversityApplyInfoId; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java index 27143ec8d..9ca291177 100644 --- a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java @@ -34,7 +34,7 @@ public interface ApplicationRepository extends JpaRepository List findApplicationsByUniversityChoices(@Param("universityIds") List universityIds, @Param("status") VerifyStatus status, @Param("term") String term); @Query(""" - SELECT a + SELECT a FROM Application a WHERE a.siteUser = :siteUser AND a.term = :term From 96e9c623c6805c8951849d5ce36677cc8abe4f2d Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 26 May 2025 22:50:27 +0900 Subject: [PATCH 11/14] =?UTF-8?q?refactor:=20Flyway=20V13=20script=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20-=20Application=20FK=EC=A0=9C=EC=95=BD?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=A0=9C=EA=B1=B0=20-=20column=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20-=20Index=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._index_and_delete_manny_to_one_mapping.sql | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql diff --git a/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql new file mode 100644 index 000000000..84cb17afd --- /dev/null +++ b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql @@ -0,0 +1,19 @@ +ALTER TABLE application DROP FOREIGN KEY FKeajojvwgn069mfxhbq5ja1sws; +ALTER TABLE application DROP FOREIGN KEY FKepp2by7frnkt1o1w3v4t4lgtu; +ALTER TABLE application DROP FOREIGN KEY FKi822ljuirbu9o0lnd9jt7l7qg; + +ALTER TABLE application RENAME COLUMN first_choice_university_id TO first_choice_university_apply_info_id; +ALTER TABLE application RENAME COLUMN second_choice_university_id TO second_choice_university_apply_info_id; +ALTER TABLE application RENAME COLUMN third_choice_university_id TO third_choice_university_apply_info_id; + +CREATE INDEX idx_app_user_term_delete + ON application(site_user_id, term, is_delete); + +CREATE INDEX idx_app_first_choice_search + ON application(verify_status, term, is_delete, first_choice_university_apply_info_id); + +CREATE INDEX idx_app_second_choice_search + ON application(verify_status, term, is_delete, second_choice_university_apply_info_id); + +CREATE INDEX idx_app_third_choice_search + ON application(verify_status, term, is_delete, third_choice_university_apply_info_id); From 81e4c308bbb96a93e0f952fd7c0268ef2510a897 Mon Sep 17 00:00:00 2001 From: lsy1307 Date: Mon, 2 Jun 2025 15:42:15 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EC=99=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EB=A6=AC=EB=B7=B0=20=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20-=20=EA=B0=80=EB=B2=BC=EC=9A=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=82=AC=ED=95=AD(=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20=ED=95=A8=EC=88=98=20=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD)=20-=20Application=20Column=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EC=BF=BC=EB=A6=AC=20=EA=B0=84?= =?UTF-8?q?=EA=B2=B0=ED=99=94=20-=20DTO=EC=97=90=20=EB=A7=A4=ED=95=91?= =?UTF-8?q?=EC=B1=85=EC=9E=84=20=EC=9D=B4=EA=B4=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/domain/Application.java | 42 +++++++++---------- .../dto/UniversityApplicantsResponse.java | 13 ++++-- .../repository/ApplicationRepository.java | 8 ++-- .../service/ApplicationQueryService.java | 42 ++++++++----------- .../service/ApplicationSubmissionService.java | 4 +- .../UniversityInfoForApplyRepository.java | 5 +-- .../custom/UniversityFilterRepository.java | 2 +- .../UniversityFilterRepositoryImpl.java | 16 ++++--- 8 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/example/solidconnection/application/domain/Application.java b/src/main/java/com/example/solidconnection/application/domain/Application.java index 9bdbbdb3c..5f982410e 100644 --- a/src/main/java/com/example/solidconnection/application/domain/Application.java +++ b/src/main/java/com/example/solidconnection/application/domain/Application.java @@ -30,11 +30,11 @@ @Index(name = "idx_app_user_term_delete", columnList = "site_user_id, term, is_delete"), @Index(name = "idx_app_first_choice_search", - columnList = "verify_status, term, is_delete, first_choice_university_apply_info_id"), + columnList = "verify_status, term, is_delete, first_choice_university_info_for_apply_id"), @Index(name = "idx_app_second_choice_search", - columnList = "verify_status, term, is_delete, second_choice_university_apply_info_id"), + columnList = "verify_status, term, is_delete, second_choice_university_info_for_apply_id"), @Index(name = "idx_app_third_choice_search", - columnList = "verify_status, term, is_delete, third_choice_university_apply_info_id") + columnList = "verify_status, term, is_delete, third_choice_university_info_for_apply_id") }) public class Application { @@ -65,14 +65,14 @@ public class Application { @Column(name="is_delete") private boolean isDelete = false; - @Column(nullable = false, name="first_choice_university_apply_info_id") - private Long firstChoiceUniversityApplyInfoId; + @Column(nullable = false , name = "first_choice_university_info_for_apply_id") + private long firstChoiceUnivApplyInfoId; - @Column(name="second_choice_university_apply_info_id") - private Long secondChoiceUniversityApplyInfoId; + @Column(name = "second_choice_university_info_for_apply_id") + private Long secondChoiceUnivApplyInfoId; - @Column(name="third_choice_university_apply_info_id") - private Long thirdChoiceUniversityApplyInfoId; + @Column(name = "third_choice_university_info_for_apply_id") + private Long thirdChoiceUnivApplyInfoId; @ManyToOne(fetch = FetchType.LAZY) private SiteUser siteUser; @@ -96,18 +96,18 @@ public Application( LanguageTest languageTest, String term, Integer updateCount, - Long firstChoiceUniversityApplyInfoId, - Long secondChoiceUniversityApplyInfoId, - Long thirdChoiceUniversityApplyInfoId, + long firstChoiceUnivApplyInfoId, + Long secondChoiceUnivApplyInfoId, + Long thirdChoiceUnivApplyInfoId, String nicknameForApply) { this.siteUser = siteUser; this.gpa = gpa; this.languageTest = languageTest; this.term = term; this.updateCount = updateCount; - this.firstChoiceUniversityApplyInfoId = firstChoiceUniversityApplyInfoId; - this.secondChoiceUniversityApplyInfoId = secondChoiceUniversityApplyInfoId; - this.thirdChoiceUniversityApplyInfoId = thirdChoiceUniversityApplyInfoId; + this.firstChoiceUnivApplyInfoId = firstChoiceUnivApplyInfoId; + this.secondChoiceUnivApplyInfoId = secondChoiceUnivApplyInfoId; + this.thirdChoiceUnivApplyInfoId = thirdChoiceUnivApplyInfoId; this.nicknameForApply = nicknameForApply; this.verifyStatus = PENDING; } @@ -117,18 +117,18 @@ public Application( Gpa gpa, LanguageTest languageTest, String term, - Long firstChoiceUniversityApplyInfoId, - Long secondChoiceUniversityApplyInfoId, - Long thirdChoiceUniversityApplyInfoId, + long firstChoiceUnivApplyInfoId, + Long secondChoiceUnivApplyInfoId, + Long thirdChoiceUnivApplyInfoId, String nicknameForApply) { this.siteUser = siteUser; this.gpa = gpa; this.languageTest = languageTest; this.term = term; this.updateCount = 1; - this.firstChoiceUniversityApplyInfoId = firstChoiceUniversityApplyInfoId; - this.secondChoiceUniversityApplyInfoId = secondChoiceUniversityApplyInfoId; - this.thirdChoiceUniversityApplyInfoId = thirdChoiceUniversityApplyInfoId; + this.firstChoiceUnivApplyInfoId = firstChoiceUnivApplyInfoId; + this.secondChoiceUnivApplyInfoId = secondChoiceUnivApplyInfoId; + this.thirdChoiceUnivApplyInfoId = thirdChoiceUnivApplyInfoId; this.nicknameForApply = nicknameForApply; this.verifyStatus = PENDING; } diff --git a/src/main/java/com/example/solidconnection/application/dto/UniversityApplicantsResponse.java b/src/main/java/com/example/solidconnection/application/dto/UniversityApplicantsResponse.java index 1d3415003..2e43ab851 100644 --- a/src/main/java/com/example/solidconnection/application/dto/UniversityApplicantsResponse.java +++ b/src/main/java/com/example/solidconnection/application/dto/UniversityApplicantsResponse.java @@ -1,5 +1,7 @@ package com.example.solidconnection.application.dto; +import com.example.solidconnection.application.domain.Application; +import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.university.domain.UniversityInfoForApply; import java.util.List; @@ -10,13 +12,18 @@ public record UniversityApplicantsResponse( String region, String country, List applicants) { - - public static UniversityApplicantsResponse of(UniversityInfoForApply universityInfoForApply, List applicant) { + public static UniversityApplicantsResponse of(UniversityInfoForApply universityInfoForApply, List applications, SiteUser siteUser) { return new UniversityApplicantsResponse( universityInfoForApply.getKoreanName(), universityInfoForApply.getStudentCapacity(), universityInfoForApply.getUniversity().getRegion().getKoreanName(), universityInfoForApply.getUniversity().getCountry().getKoreanName(), - applicant); + applications.stream() + .map(application -> ApplicantResponse.of(application, isUsers(application, siteUser))) + .toList()); + } + + private static boolean isUsers(Application application, SiteUser siteUser) { + return application.getSiteUser().getId().equals(siteUser.getId()); } } diff --git a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java index 9ca291177..badbc8254 100644 --- a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java @@ -24,14 +24,14 @@ public interface ApplicationRepository extends JpaRepository SELECT a FROM Application a JOIN FETCH a.siteUser - WHERE (a.firstChoiceUniversityApplyInfoId IN :universityIds - OR a.secondChoiceUniversityApplyInfoId IN :universityIds - OR a.thirdChoiceUniversityApplyInfoId IN :universityIds) + WHERE (a.firstChoiceUnivApplyInfoId IN :universityIds + OR a.secondChoiceUnivApplyInfoId IN :universityIds + OR a.thirdChoiceUnivApplyInfoId IN :universityIds) AND a.verifyStatus = :status AND a.term = :term AND a.isDelete = false """) - List findApplicationsByUniversityChoices(@Param("universityIds") List universityIds, @Param("status") VerifyStatus status, @Param("term") String term); + List findAllByUnivApplyInfoIds(@Param("universityIds") List universityIds, @Param("status") VerifyStatus status, @Param("term") String term); @Query(""" SELECT a diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java index ff0f132ff..8e06ad79f 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java @@ -41,20 +41,18 @@ public class ApplicationQueryService { // todo: 캐싱 정책 변경 시 수정 필요 @Transactional(readOnly = true) public ApplicationsResponse getApplicants(SiteUser siteUser, String regionCode, String keyword) { - // 1. 대학 ID 필터링 (regionCode, keyword) - List universityIds = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); - if (universityIds.isEmpty()) { + // 1. 대학 지원 정보 필터링 (regionCode, keyword) + List univApplyInfos = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); + if (univApplyInfos.isEmpty()) { return new ApplicationsResponse(List.of(), List.of(), List.of()); } - // 2. 조건에 맞는 모든 Application 한 번에 조회 - List applications = applicationRepository.findApplicationsByUniversityChoices(universityIds, VerifyStatus.APPROVED, term); - - // 3. 대학정보 조회 - List universityInfosForApply = universityInfoForApplyRepository.findByUniversityIdsWithUniversityAndLocation(universityIds); - - // 4. 지원서 분류 및 DTO 변환 - return classifyApplicationsByChoice(universityInfosForApply, applications, siteUser); + List univApplyInfoIds = univApplyInfos.stream() + .map(UniversityInfoForApply::getId) + .toList(); + List applications = applicationRepository.findAllByUnivApplyInfoIds(univApplyInfoIds, VerifyStatus.APPROVED, term); + // 3. 지원서 분류 및 DTO 변환 + return classifyApplicationsByChoice(univApplyInfos, applications, siteUser); } @Transactional(readOnly = true) @@ -62,9 +60,9 @@ public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { Application userLatestApplication = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term); List universityInfoForApplyIds = Stream.of( - userLatestApplication.getFirstChoiceUniversityApplyInfoId(), - userLatestApplication.getSecondChoiceUniversityApplyInfoId(), - userLatestApplication.getThirdChoiceUniversityApplyInfoId() + userLatestApplication.getFirstChoiceUnivApplyInfoId(), + userLatestApplication.getSecondChoiceUnivApplyInfoId(), + userLatestApplication.getThirdChoiceUnivApplyInfoId() ) .filter(Objects::nonNull) .collect(Collectors.toList()); @@ -73,8 +71,8 @@ public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { return new ApplicationsResponse(List.of(), List.of(), List.of()); } - List applications = applicationRepository.findApplicationsByUniversityChoices(universityInfoForApplyIds, VerifyStatus.APPROVED, term); - List universityInfosForApply = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityInfoForApplyIds); + List applications = applicationRepository.findAllByUnivApplyInfoIds(universityInfoForApplyIds, VerifyStatus.APPROVED, term); + List universityInfosForApply = universityInfoForApplyRepository.findAllByUniversityIds(universityInfoForApplyIds); return classifyApplicationsByChoice(universityInfosForApply, applications, siteUser); } @@ -83,9 +81,9 @@ private ApplicationsResponse classifyApplicationsByChoice( List universityInfosForApply, List applications, SiteUser siteUser) { - Map> firstChoiceMap = createChoiceMap(applications, Application::getFirstChoiceUniversityApplyInfoId); - Map> secondChoiceMap = createChoiceMap(applications, Application::getSecondChoiceUniversityApplyInfoId); - Map> thirdChoiceMap = createChoiceMap(applications, Application::getThirdChoiceUniversityApplyInfoId); + Map> firstChoiceMap = createChoiceMap(applications, Application::getFirstChoiceUnivApplyInfoId); + Map> secondChoiceMap = createChoiceMap(applications, Application::getSecondChoiceUnivApplyInfoId); + Map> thirdChoiceMap = createChoiceMap(applications, Application::getThirdChoiceUnivApplyInfoId); List firstChoiceApplicants = createUniversityApplicantsResponses(universityInfosForApply, firstChoiceMap, siteUser); @@ -117,11 +115,7 @@ private List createUniversityApplicantsResponses( Map> choiceMap, SiteUser siteUser) { return universityInfosForApply.stream() - .map(uia -> UniversityApplicantsResponse.of( - uia, - choiceMap.getOrDefault(uia.getId(), List.of()).stream() - .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) - .toList())) + .map(uia -> UniversityApplicantsResponse.of(uia, choiceMap.getOrDefault(uia.getId(), List.of()), siteUser)) .toList(); } diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java index d9d78c70f..721693f38 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java @@ -6,14 +6,12 @@ import com.example.solidconnection.application.dto.ApplyRequest; import com.example.solidconnection.application.dto.UniversityChoiceRequest; import com.example.solidconnection.application.repository.ApplicationRepository; -import com.example.solidconnection.cache.annotation.DefaultCacheOut; import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.score.domain.GpaScore; import com.example.solidconnection.score.domain.LanguageTestScore; import com.example.solidconnection.score.repository.GpaScoreRepository; import com.example.solidconnection.score.repository.LanguageTestScoreRepository; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.university.domain.UniversityInfoForApply; import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -50,7 +48,7 @@ public ApplicationSubmissionResponse apply(SiteUser siteUser, ApplyRequest apply GpaScore gpaScore = getValidGpaScore(siteUser, applyRequest.gpaScoreId()); LanguageTestScore languageTestScore = getValidLanguageTestScore(siteUser, applyRequest.languageTestScoreId()); - Long firstChoiceUniversityId = universityChoiceRequest.firstChoiceUniversityId(); + long firstChoiceUniversityId = universityChoiceRequest.firstChoiceUniversityId(); Long secondChoiceUniversityId = universityChoiceRequest.secondChoiceUniversityId(); Long thirdChoiceUniversityId = universityChoiceRequest.thirdChoiceUniversityId(); diff --git a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java index 6e21abdd4..73a5ee14b 100644 --- a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java @@ -72,7 +72,7 @@ default UniversityInfoForApply getUniversityInfoForApplyById(Long id) { JOIN FETCH u.region r WHERE uifa.id IN :ids """) - List findByIdsWithUniversityAndLocation(@Param("ids") List ids); + List findAllByUniversityIds(@Param("ids") List ids); @Query(""" SELECT DISTINCT uifa @@ -83,5 +83,4 @@ default UniversityInfoForApply getUniversityInfoForApplyById(Long id) { WHERE u.id IN :universityIds """) List findByUniversityIdsWithUniversityAndLocation(@Param("universityIds") List universityIds); - -} +} \ No newline at end of file diff --git a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java index ef0cd8d93..93850a2f4 100644 --- a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepository.java @@ -8,7 +8,7 @@ public interface UniversityFilterRepository { - List findByRegionCodeAndKeywords(String regionCode, List keywords); + List findByRegionCodeAndKeywords(String regionCode, List keywords); List findByRegionCodeAndKeywordsAndLanguageTestTypeAndTestScoreAndTerm( String regionCode, List keywords, LanguageTestType testType, String testScore, String term); diff --git a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java index e66c5454a..b01095996 100644 --- a/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java +++ b/src/main/java/com/example/solidconnection/university/repository/custom/UniversityFilterRepositoryImpl.java @@ -5,8 +5,8 @@ import com.example.solidconnection.university.domain.LanguageTestType; import com.example.solidconnection.university.domain.QUniversity; import com.example.solidconnection.university.domain.QUniversityInfoForApply; -import com.example.solidconnection.university.domain.University; import com.example.solidconnection.university.domain.UniversityInfoForApply; +import com.example.solidconnection.university.domain.QLanguageRequirement; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringPath; @@ -28,16 +28,19 @@ public UniversityFilterRepositoryImpl(EntityManager em) { } @Override - public List findByRegionCodeAndKeywords(String regionCode, List keywords) { + public List findByRegionCodeAndKeywords(String regionCode, List keywords) { + QUniversityInfoForApply universityInfoForApply = QUniversityInfoForApply.universityInfoForApply; QUniversity university = QUniversity.university; QCountry country = QCountry.country; QRegion region = QRegion.region; + QLanguageRequirement languageRequirement = QLanguageRequirement.languageRequirement; return queryFactory - .select(university.id) - .from(university) - .join(university.country, country) - .join(country.region, region) + .selectFrom(universityInfoForApply) + .join(universityInfoForApply.university, university).fetchJoin() + .join(university.country, country).fetchJoin() + .join(country.region, region).fetchJoin() + .leftJoin(universityInfoForApply.languageRequirements, languageRequirement).fetchJoin() .where( regionCodeEq(region, regionCode) .and(countryOrUniversityContainsKeyword(country, university, keywords)) @@ -46,6 +49,7 @@ public List findByRegionCodeAndKeywords(String regionCode, List ke .fetch(); } + private BooleanExpression regionCodeEq(QRegion region, String regionCode) { if (regionCode == null || regionCode.isEmpty()) { return Expressions.asBoolean(true).isTrue(); From 716639f77cbc0e5189385621621bfac82241ceb6 Mon Sep 17 00:00:00 2001 From: lsy1307 Date: Mon, 23 Jun 2025 13:23:37 +0900 Subject: [PATCH 13/14] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20Flyway?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=20=EC=88=98=EC=A0=95=20-=20Flyway=20Column=EB=AA=85?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._index_and_delete_manny_to_one_mapping.sql | 6 ++--- .../service/ApplicationQueryServiceTest.java | 24 ++++++++----------- .../ApplicationSubmissionServiceTest.java | 6 ++--- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql index 84cb17afd..1b4179894 100644 --- a/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql +++ b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql @@ -2,9 +2,9 @@ ALTER TABLE application DROP FOREIGN KEY FKeajojvwgn069mfxhbq5ja1sws; ALTER TABLE application DROP FOREIGN KEY FKepp2by7frnkt1o1w3v4t4lgtu; ALTER TABLE application DROP FOREIGN KEY FKi822ljuirbu9o0lnd9jt7l7qg; -ALTER TABLE application RENAME COLUMN first_choice_university_id TO first_choice_university_apply_info_id; -ALTER TABLE application RENAME COLUMN second_choice_university_id TO second_choice_university_apply_info_id; -ALTER TABLE application RENAME COLUMN third_choice_university_id TO third_choice_university_apply_info_id; +ALTER TABLE application RENAME COLUMN first_choice_university_id TO first_choice_university_info_for_apply_id; +ALTER TABLE application RENAME COLUMN second_choice_university_id TO second_choice_university_info_for_apply_id; +ALTER TABLE application RENAME COLUMN third_choice_university_id TO third_choice_university_info_for_apply_id; CREATE INDEX idx_app_user_term_delete ON application(site_user_id, term, is_delete); diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java index d95b89e26..1a0f927a2 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java @@ -71,7 +71,6 @@ class ApplicationQueryServiceTest { private LanguageTestScore languageTestScore2; private LanguageTestScore languageTestScore3; - private UniversityInfoForApply 괌대학_A_지원_정보; private UniversityInfoForApply 괌대학_B_지원_정보; private UniversityInfoForApply 서던덴마크대학교_지원_정보; @@ -142,11 +141,11 @@ class 지원자_목록_조회_테스트 { // then assertThat(response.firstChoice()).containsAll(List.of( UniversityApplicantsResponse.of(괌대학_A_지원_정보, - List.of(ApplicantResponse.of(application1, true))), + List.of(application1), user1), UniversityApplicantsResponse.of(괌대학_B_지원_정보, - List.of(ApplicantResponse.of(application2, false))), + List.of(application2), user1), UniversityApplicantsResponse.of(서던덴마크대학교_지원_정보, - List.of(ApplicantResponse.of(application3, false))) + List.of(application3), user1) )); } @@ -194,9 +193,9 @@ class 지원자_목록_조회_테스트 { // then assertThat(response.firstChoice()).containsExactlyInAnyOrder( UniversityApplicantsResponse.of(괌대학_A_지원_정보, - List.of(ApplicantResponse.of(application1, true))), + List.of(application1), user1), UniversityApplicantsResponse.of(괌대학_B_지원_정보, - List.of(ApplicantResponse.of(application2, false))) + List.of(application2), user1) ); } @@ -244,9 +243,9 @@ class 지원자_목록_조회_테스트 { // then assertThat(response.firstChoice()).containsExactlyInAnyOrder( UniversityApplicantsResponse.of(괌대학_A_지원_정보, - List.of(ApplicantResponse.of(application1, true))), + List.of(application1), user1), UniversityApplicantsResponse.of(괌대학_B_지원_정보, - List.of(ApplicantResponse.of(application2, false))) + List.of(application2), user1) ); } @@ -274,7 +273,7 @@ class 지원자_목록_조회_테스트 { // then assertThat(response.firstChoice()).doesNotContainAnyElementsOf(List.of( UniversityApplicantsResponse.of(괌대학_A_지원_정보, - List.of(ApplicantResponse.of(application, true))) + List.of(application), user1) )); } @@ -321,7 +320,6 @@ class 지원자_목록_조회_테스트 { @Nested class 경쟁자_목록_조회_테스트 { - @Test void 이번_학기_지원한_대학의_경쟁자_목록을_조회한다() { // given @@ -360,10 +358,8 @@ class 경쟁자_목록_조회_테스트 { // then assertThat(response.firstChoice()).containsExactlyInAnyOrder( - UniversityApplicantsResponse.of(괌대학_A_지원_정보, List.of( - ApplicantResponse.of(application1, true), - ApplicantResponse.of(application2, false) - )) + UniversityApplicantsResponse.of(괌대학_A_지원_정보, + List.of(application1, application2), user1) ); } diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java index e57c77d58..2718fb90b 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java @@ -92,11 +92,11 @@ void setUp() { .isEqualTo(VerifyStatus.APPROVED), () -> assertThat(savedApplication.isDelete()) .isFalse(), - () -> assertThat(savedApplication.getFirstChoiceUniversityApplyInfoId()) + () -> assertThat(savedApplication.getFirstChoiceUnivApplyInfoId()) .isEqualTo(괌대학_A_지원_정보.getId()), - () -> assertThat(savedApplication.getSecondChoiceUniversityApplyInfoId()) + () -> assertThat(savedApplication.getSecondChoiceUnivApplyInfoId()) .isEqualTo(괌대학_B_지원_정보.getId()), - () -> assertThat(savedApplication.getThirdChoiceUniversityApplyInfoId()) + () -> assertThat(savedApplication.getThirdChoiceUnivApplyInfoId()) .isEqualTo(서던덴마크대학교_지원_정보.getId()) ); } From 95bc7747ab8eadabe11f07d259a8c4cd56351efb Mon Sep 17 00:00:00 2001 From: Yeonri Date: Tue, 24 Jun 2025 16:37:05 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor:=20Flyway=20V13=20FK=EC=A0=9C?= =?UTF-8?q?=EC=95=BD=EC=A1=B0=EA=B1=B4=20=EC=9C=A0=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._add_application_index_and_delete_manny_to_one_mapping.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql index 1b4179894..3f3018724 100644 --- a/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql +++ b/src/main/resources/db/migration/V13_add_application_index_and_delete_manny_to_one_mapping.sql @@ -1,7 +1,3 @@ -ALTER TABLE application DROP FOREIGN KEY FKeajojvwgn069mfxhbq5ja1sws; -ALTER TABLE application DROP FOREIGN KEY FKepp2by7frnkt1o1w3v4t4lgtu; -ALTER TABLE application DROP FOREIGN KEY FKi822ljuirbu9o0lnd9jt7l7qg; - ALTER TABLE application RENAME COLUMN first_choice_university_id TO first_choice_university_info_for_apply_id; ALTER TABLE application RENAME COLUMN second_choice_university_id TO second_choice_university_info_for_apply_id; ALTER TABLE application RENAME COLUMN third_choice_university_id TO third_choice_university_info_for_apply_id;