From 2367505fb5b880a336193a51f01ec50c6d4271de Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Thu, 23 May 2024 03:47:49 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20Staga=EC=97=90=20`@OneToMany`=20?= =?UTF-8?q?=EA=B4=80=EA=B3=84=EC=9D=98=20List=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/StageCreateService.java | 12 +----- .../command/StageDeleteService.java | 5 +-- .../command/StageUpdateService.java | 10 +---- .../java/com/festago/stage/domain/Stage.java | 25 +++++++++++- .../stage/repository/StageRepository.java | 20 ++++++++-- .../command/StageCreateServiceTest.java | 15 +++---- .../command/StageDeleteServiceTest.java | 21 +--------- .../command/StageUpdateServiceTest.java | 9 +++-- .../com/festago/stage/domain/StageTest.java | 39 +++++++++++++++++++ .../repository/MemoryStageRepository.java | 11 ------ 10 files changed, 96 insertions(+), 71 deletions(-) diff --git a/backend/src/main/java/com/festago/stage/application/command/StageCreateService.java b/backend/src/main/java/com/festago/stage/application/command/StageCreateService.java index b70075cca..194f02995 100644 --- a/backend/src/main/java/com/festago/stage/application/command/StageCreateService.java +++ b/backend/src/main/java/com/festago/stage/application/command/StageCreateService.java @@ -7,10 +7,8 @@ import com.festago.festival.domain.Festival; import com.festago.festival.repository.FestivalRepository; import com.festago.stage.domain.Stage; -import com.festago.stage.domain.StageArtist; import com.festago.stage.dto.command.StageCreateCommand; import com.festago.stage.dto.event.StageCreatedEvent; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import java.util.List; import lombok.RequiredArgsConstructor; @@ -28,7 +26,6 @@ public class StageCreateService { private final StageRepository stageRepository; private final FestivalRepository festivalRepository; private final ArtistRepository artistRepository; - private final StageArtistRepository stageArtistRepository; private final ApplicationEventPublisher eventPublisher; public Long createStage(StageCreateCommand command) { @@ -40,7 +37,7 @@ public Long createStage(StageCreateCommand command) { festival )); List artistIds = command.artistIds(); - createStageArtist(artistIds, stage); + stage.renewArtists(artistIds); eventPublisher.publishEvent(new StageCreatedEvent(stage)); return stage.getId(); } @@ -49,12 +46,7 @@ private void validate(StageCreateCommand command) { List artistIds = command.artistIds(); Validator.maxSize(artistIds, MAX_ARTIST_SIZE, "artistIds"); Validator.notDuplicate(artistIds, "artistIds"); - } - - private void createStageArtist(List artistIds, Stage stage) { - if (artistRepository.countByIdIn(artistIds) == artistIds.size()) { - artistIds.forEach(artistId -> stageArtistRepository.save(new StageArtist(stage.getId(), artistId))); - } else { + if (artistRepository.countByIdIn(artistIds) != artistIds.size()) { throw new NotFoundException(ErrorCode.ARTIST_NOT_FOUND); } } diff --git a/backend/src/main/java/com/festago/stage/application/command/StageDeleteService.java b/backend/src/main/java/com/festago/stage/application/command/StageDeleteService.java index 73149505c..0dae753b3 100644 --- a/backend/src/main/java/com/festago/stage/application/command/StageDeleteService.java +++ b/backend/src/main/java/com/festago/stage/application/command/StageDeleteService.java @@ -1,7 +1,6 @@ package com.festago.stage.application.command; import com.festago.stage.dto.event.StageDeletedEvent; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; @@ -14,12 +13,10 @@ public class StageDeleteService { private final StageRepository stageRepository; - private final StageArtistRepository stageArtistRepository; private final ApplicationEventPublisher eventPublisher; public void deleteStage(Long stageId) { - stageRepository.findByIdWithFetch(stageId).ifPresent(stage -> { - stageArtistRepository.deleteByStageId(stageId); + stageRepository.findById(stageId).ifPresent(stage -> { stageRepository.deleteById(stageId); eventPublisher.publishEvent(new StageDeletedEvent(stage)); }); diff --git a/backend/src/main/java/com/festago/stage/application/command/StageUpdateService.java b/backend/src/main/java/com/festago/stage/application/command/StageUpdateService.java index 9b292c00b..ef233b2e1 100644 --- a/backend/src/main/java/com/festago/stage/application/command/StageUpdateService.java +++ b/backend/src/main/java/com/festago/stage/application/command/StageUpdateService.java @@ -5,10 +5,8 @@ import com.festago.common.exception.NotFoundException; import com.festago.common.util.Validator; import com.festago.stage.domain.Stage; -import com.festago.stage.domain.StageArtist; import com.festago.stage.dto.command.StageUpdateCommand; import com.festago.stage.dto.event.StageUpdatedEvent; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import java.time.LocalDateTime; import java.util.List; @@ -26,7 +24,6 @@ public class StageUpdateService { private final StageRepository stageRepository; private final ArtistRepository artistRepository; - private final StageArtistRepository stageArtistRepository; private final ApplicationEventPublisher eventPublisher; public void updateStage(Long stageId, StageUpdateCommand command) { @@ -37,7 +34,7 @@ public void updateStage(Long stageId, StageUpdateCommand command) { Stage stage = stageRepository.findByIdWithFetch(stageId) .orElseThrow(() -> new NotFoundException(ErrorCode.STAGE_NOT_FOUND)); stage.changeTime(startTime, ticketOpenTime); - renewStageArtist(stage, artistIds); + stage.renewArtists(artistIds); eventPublisher.publishEvent(new StageUpdatedEvent(stage)); } @@ -45,13 +42,8 @@ private void validate(StageUpdateCommand command) { List artistIds = command.artistIds(); Validator.maxSize(artistIds, MAX_ARTIST_SIZE, "artistIds"); Validator.notDuplicate(artistIds, "artistIds"); - } - - private void renewStageArtist(Stage stage, List artistIds) { if (artistRepository.countByIdIn(artistIds) != artistIds.size()) { throw new NotFoundException(ErrorCode.ARTIST_NOT_FOUND); } - stageArtistRepository.deleteByStageId(stage.getId()); - artistIds.forEach(artistId -> stageArtistRepository.save(new StageArtist(stage.getId(), artistId))); } } diff --git a/backend/src/main/java/com/festago/stage/domain/Stage.java b/backend/src/main/java/com/festago/stage/domain/Stage.java index 9578e1270..514583325 100644 --- a/backend/src/main/java/com/festago/stage/domain/Stage.java +++ b/backend/src/main/java/com/festago/stage/domain/Stage.java @@ -6,6 +6,7 @@ import com.festago.common.util.Validator; import com.festago.festival.domain.Festival; import com.festago.ticket.domain.Ticket; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; @@ -17,6 +18,8 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -41,7 +44,8 @@ public class Stage extends BaseTimeEntity { @OneToMany(mappedBy = "stage", fetch = FetchType.LAZY) private List tickets = new ArrayList<>(); - @OneToMany(fetch = FetchType.LAZY, mappedBy = "stageId") + @OneToMany(fetch = FetchType.LAZY, mappedBy = "stageId", orphanRemoval = true, + cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) private List artists = new ArrayList<>(); public Stage(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) { @@ -87,6 +91,25 @@ public void changeTime(LocalDateTime startTime, LocalDateTime ticketOpenTime) { this.ticketOpenTime = ticketOpenTime; } + public void renewArtists(List artistIds) { + artists.removeIf(artist -> !artistIds.contains(artist.getArtistId())); + Set existsArtistIds = artists.stream() + .map(StageArtist::getArtistId) + .collect(Collectors.toSet()); + for (Long artistId : artistIds) { + if (!existsArtistIds.contains(artistId)) { + artists.add(new StageArtist(this.id, artistId)); + } + } + } + + public List getArtistIds() { + return artists.stream() + .map(StageArtist::getArtistId) + .sorted() + .toList(); + } + public Long getId() { return id; } diff --git a/backend/src/main/java/com/festago/stage/repository/StageRepository.java b/backend/src/main/java/com/festago/stage/repository/StageRepository.java index 584107e74..8bf8e7e22 100644 --- a/backend/src/main/java/com/festago/stage/repository/StageRepository.java +++ b/backend/src/main/java/com/festago/stage/repository/StageRepository.java @@ -1,11 +1,19 @@ package com.festago.stage.repository; +import com.festago.common.exception.ErrorCode; +import com.festago.common.exception.NotFoundException; import com.festago.stage.domain.Stage; import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; +import org.springframework.data.repository.query.Param; -public interface StageRepository extends Repository, StageRepositoryCustom { +public interface StageRepository extends Repository { + + default Stage getOrThrow(Long stageId) { + return findById(stageId).orElseThrow(() -> new NotFoundException(ErrorCode.STAGE_NOT_FOUND)); + } Stage save(Stage stage); @@ -13,10 +21,16 @@ public interface StageRepository extends Repository, StageRepositor void deleteById(Long stageId); - void flush(); - boolean existsByFestivalId(Long festivalId); List findAllByFestivalId(Long festivalId); + @Query(""" + select s + from Stage s + join fetch s.festival + left join fetch s.artists + where s.id = :id + """) + Optional findByIdWithFetch(@Param("id") Long id); } diff --git a/backend/src/test/java/com/festago/stage/application/command/StageCreateServiceTest.java b/backend/src/test/java/com/festago/stage/application/command/StageCreateServiceTest.java index e49fa58ff..f0c58b812 100644 --- a/backend/src/test/java/com/festago/stage/application/command/StageCreateServiceTest.java +++ b/backend/src/test/java/com/festago/stage/application/command/StageCreateServiceTest.java @@ -14,22 +14,21 @@ import com.festago.festival.domain.Festival; import com.festago.festival.repository.FestivalRepository; import com.festago.festival.repository.MemoryFestivalRepository; +import com.festago.stage.domain.Stage; import com.festago.stage.dto.command.StageCreateCommand; -import com.festago.stage.repository.MemoryStageArtistRepository; import com.festago.stage.repository.MemoryStageRepository; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import com.festago.support.fixture.ArtistFixture; import com.festago.support.fixture.FestivalFixture; import java.time.LocalDate; import java.util.List; -import java.util.Set; import java.util.stream.LongStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationEventPublisher; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") @@ -41,8 +40,6 @@ class StageCreateServiceTest { ArtistRepository artistRepository; - StageArtistRepository stageArtistRepository; - StageCreateService stageCreateService; LocalDate festivalStartDate = LocalDate.parse("2077-06-30"); @@ -59,13 +56,11 @@ void setUp() { stageRepository = new MemoryStageRepository(); festivalRepository = new MemoryFestivalRepository(); artistRepository = new MemoryArtistRepository(); - stageArtistRepository = new MemoryStageArtistRepository(); stageCreateService = new StageCreateService( stageRepository, festivalRepository, artistRepository, - stageArtistRepository, - mock() + mock(ApplicationEventPublisher.class) ); 테코대학교_축제 = festivalRepository.save( @@ -184,8 +179,8 @@ class createStage { Long stageId = stageCreateService.createStage(command); // then - Set stageArtists = stageArtistRepository.findAllArtistIdByStageId(stageId); - assertThat(stageArtists) + Stage stage = stageRepository.getOrThrow(stageId); + assertThat(stage.getArtistIds()) .containsExactlyInAnyOrder(에픽하이.getId(), 소녀시대.getId(), 뉴진스.getId()); } } diff --git a/backend/src/test/java/com/festago/stage/application/command/StageDeleteServiceTest.java b/backend/src/test/java/com/festago/stage/application/command/StageDeleteServiceTest.java index d81070c4d..02903446a 100644 --- a/backend/src/test/java/com/festago/stage/application/command/StageDeleteServiceTest.java +++ b/backend/src/test/java/com/festago/stage/application/command/StageDeleteServiceTest.java @@ -11,13 +11,10 @@ import com.festago.festival.repository.FestivalRepository; import com.festago.festival.repository.MemoryFestivalRepository; import com.festago.stage.domain.Stage; -import com.festago.stage.repository.MemoryStageArtistRepository; import com.festago.stage.repository.MemoryStageRepository; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import com.festago.support.fixture.ArtistFixture; import com.festago.support.fixture.FestivalFixture; -import com.festago.support.fixture.StageArtistFixture; import com.festago.support.fixture.StageFixture; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; @@ -25,7 +22,7 @@ import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; - +import org.springframework.context.ApplicationEventPublisher; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") @@ -34,7 +31,6 @@ class StageDeleteServiceTest { ArtistRepository artistRepository; FestivalRepository festivalRepository; StageRepository stageRepository; - StageArtistRepository stageArtistRepository; StageDeleteService stageDeleteService; LocalDateTime stageStartTime = LocalDateTime.parse("2077-06-30T18:00:00"); @@ -50,8 +46,7 @@ void setUp() { artistRepository = new MemoryArtistRepository(); festivalRepository = new MemoryFestivalRepository(); stageRepository = new MemoryStageRepository(); - stageArtistRepository = new MemoryStageArtistRepository(); - stageDeleteService = new StageDeleteService(stageRepository, stageArtistRepository, mock()); + stageDeleteService = new StageDeleteService(stageRepository, mock(ApplicationEventPublisher.class)); 테코대학교_축제 = festivalRepository.save( FestivalFixture.builder() @@ -70,9 +65,6 @@ void setUp() { 에픽하이 = artistRepository.save(ArtistFixture.builder().name("에픽하이").build()); 소녀시대 = artistRepository.save(ArtistFixture.builder().name("소녀시대").build()); 뉴진스 = artistRepository.save(ArtistFixture.builder().name("뉴진스").build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 에픽하이.getId()).build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 소녀시대.getId()).build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 뉴진스.getId()).build()); } @Nested @@ -96,14 +88,5 @@ class deleteStage { // then assertThat(stageRepository.findById(테코대학교_축제_공연.getId())).isEmpty(); } - - @Test - void 성공하면_식별자에_대한_StageArtist가_삭제된다() { - // when - stageDeleteService.deleteStage(테코대학교_축제_공연.getId()); - - // then - assertThat(stageArtistRepository.findAllArtistIdByStageId(테코대학교_축제_공연.getId())).isEmpty(); - } } } diff --git a/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java b/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java index cf5e173ec..a15c5bc86 100644 --- a/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java +++ b/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java @@ -24,13 +24,13 @@ import com.festago.support.fixture.StageFixture; import java.time.LocalDateTime; import java.util.List; -import java.util.Set; import java.util.stream.LongStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationEventPublisher; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") @@ -54,7 +54,8 @@ void setUp() { stageRepository = new MemoryStageRepository(); artistRepository = new MemoryArtistRepository(); stageArtistRepository = new MemoryStageArtistRepository(); - stageUpdateService = new StageUpdateService(stageRepository, artistRepository, stageArtistRepository, mock()); + stageUpdateService = new StageUpdateService(stageRepository, artistRepository, + mock(ApplicationEventPublisher.class)); 테코대학교_축제 = FestivalFixture.builder() .name("테코대학교 축제") @@ -193,8 +194,8 @@ class updateStage { stageUpdateService.updateStage(테코대학교_축제_공연.getId(), command); // then - Set artistIds = stageArtistRepository.findAllArtistIdByStageId(테코대학교_축제_공연.getId()); - assertThat(artistIds) + Stage stage = stageRepository.getOrThrow(테코대학교_축제_공연.getId()); + assertThat(stage.getArtistIds()) .containsExactly(에픽하이.getId()); } } diff --git a/backend/src/test/java/com/festago/stage/domain/StageTest.java b/backend/src/test/java/com/festago/stage/domain/StageTest.java index fca2cca25..5b4e11b8b 100644 --- a/backend/src/test/java/com/festago/stage/domain/StageTest.java +++ b/backend/src/test/java/com/festago/stage/domain/StageTest.java @@ -2,6 +2,7 @@ import static com.festago.common.exception.ErrorCode.INVALID_STAGE_START_TIME; import static com.festago.common.exception.ErrorCode.INVALID_TICKET_OPEN_TIME; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -10,8 +11,11 @@ import com.festago.support.fixture.FestivalFixture; import com.festago.support.fixture.StageFixture; import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -100,4 +104,39 @@ class StageTest { .festival(festival) .build()); } + + @Nested + class renewArtists { + + Stage stage; + + @BeforeEach + void setUp() { + stage = StageFixture.builder().id(1L).build(); + } + + @Test + void 아티스트를_추가할_수_있다() { + // when + stage.renewArtists(List.of(1L, 2L, 3L)); + + // then + assertThat(stage.getArtistIds()) + .containsExactly(1L, 2L, 3L); + } + + @Test + void 추가하려는_아티스트가_기존_아티스트에_없으면_기존_아티스트는_삭제된다() { + // given + stage.renewArtists(List.of(1L)); + + // when + stage.renewArtists(List.of(2L, 3L)); + + // then + assertThat(stage.getArtistIds()) + .doesNotContain(1L) + .containsExactly(2L, 3L); + } + } } diff --git a/backend/src/test/java/com/festago/stage/repository/MemoryStageRepository.java b/backend/src/test/java/com/festago/stage/repository/MemoryStageRepository.java index 66067201e..cfb4ff731 100644 --- a/backend/src/test/java/com/festago/stage/repository/MemoryStageRepository.java +++ b/backend/src/test/java/com/festago/stage/repository/MemoryStageRepository.java @@ -8,12 +8,6 @@ public class MemoryStageRepository extends AbstractMemoryRepository implements StageRepository { - - @Override - public void flush() { - //NOOP - } - @Override public boolean existsByFestivalId(Long festivalId) { return memory.values().stream() @@ -27,11 +21,6 @@ public List findAllByFestivalId(Long festivalId) { .toList(); } - @Override - public List findAllDetailByFestivalId(Long festivalId) { - return findAllByFestivalId(festivalId); - } - @Override public Optional findByIdWithFetch(Long id) { return findById(id); From 5bf48097fa9bcc5fbbedae31b79f510f8ed1c8e3 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Thu, 23 May 2024 03:52:14 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20StageArtistRepository=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdminQueryInfoRenewalService.java | 8 +- ...dminStageIdResolverQueryDslRepository.java | 33 ------ .../AdminStageResolverQueryDslRepository.java | 33 ++++++ .../StageQueryInfoEventListener.java | 4 +- .../application/StageQueryInfoService.java | 27 ++--- .../FestivalIdStageArtistsResolverImpl.java | 38 ------ ...estivalIdStageArtistsQueryDslResolver.java | 33 ++++++ .../repository/StageArtistRepository.java | 12 -- .../repository/StageRepositoryCustom.java | 12 -- .../repository/StageRepositoryCustomImpl.java | 37 ------ ...nStageResolverQueryDslRepositoryTest.java} | 20 ++-- .../StageQueryInfoServiceTest.java | 53 ++++----- .../command/StageUpdateServiceTest.java | 17 ++- ...valIdStageArtistsQueryDslResolverTest.java | 96 +++++++++++++++ .../MemoryStageArtistRepository.java | 28 +---- .../stage/repository/StageRepositoryTest.java | 112 ------------------ 16 files changed, 216 insertions(+), 347 deletions(-) delete mode 100644 backend/src/main/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepository.java create mode 100644 backend/src/main/java/com/festago/admin/repository/AdminStageResolverQueryDslRepository.java delete mode 100644 backend/src/main/java/com/festago/stage/domain/FestivalIdStageArtistsResolverImpl.java create mode 100644 backend/src/main/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolver.java delete mode 100644 backend/src/main/java/com/festago/stage/repository/StageRepositoryCustom.java delete mode 100644 backend/src/main/java/com/festago/stage/repository/StageRepositoryCustomImpl.java rename backend/src/test/java/com/festago/admin/repository/{AdminStageIdResolverQueryDslRepositoryTest.java => AdminStageResolverQueryDslRepositoryTest.java} (77%) create mode 100644 backend/src/test/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolverTest.java delete mode 100644 backend/src/test/java/com/festago/stage/repository/StageRepositoryTest.java diff --git a/backend/src/main/java/com/festago/admin/application/AdminQueryInfoRenewalService.java b/backend/src/main/java/com/festago/admin/application/AdminQueryInfoRenewalService.java index 3d481ab51..12f7b4682 100644 --- a/backend/src/main/java/com/festago/admin/application/AdminQueryInfoRenewalService.java +++ b/backend/src/main/java/com/festago/admin/application/AdminQueryInfoRenewalService.java @@ -1,7 +1,7 @@ package com.festago.admin.application; import com.festago.admin.repository.AdminFestivalIdResolverQueryDslRepository; -import com.festago.admin.repository.AdminStageIdResolverQueryDslRepository; +import com.festago.admin.repository.AdminStageResolverQueryDslRepository; import com.festago.festival.application.FestivalQueryInfoArtistRenewService; import com.festago.stage.application.StageQueryInfoService; import java.time.LocalDate; @@ -19,12 +19,12 @@ public class AdminQueryInfoRenewalService { private final FestivalQueryInfoArtistRenewService festivalQueryInfoArtistRenewService; private final StageQueryInfoService stageQueryInfoService; - private final AdminStageIdResolverQueryDslRepository adminStageIdResolverQueryDslRepository; + private final AdminStageResolverQueryDslRepository adminStageResolverQueryDslRepository; private final AdminFestivalIdResolverQueryDslRepository adminFestivalIdResolverQueryDslRepository; public void renewalByFestivalId(Long festivalId) { festivalQueryInfoArtistRenewService.renewArtistInfo(festivalId); - adminStageIdResolverQueryDslRepository.findStageIdsByFestivalId(festivalId) + adminStageResolverQueryDslRepository.findStageByFestivalId(festivalId) .forEach(stageQueryInfoService::renewalStageQueryInfo); } @@ -32,7 +32,7 @@ public void renewalByFestivalStartDatePeriod(LocalDate to, LocalDate end) { List festivalIds = adminFestivalIdResolverQueryDslRepository.findFestivalIdsByStartDatePeriod(to, end); log.info("{}개의 축제에 대해 QueryInfo를 새로 갱신합니다.", festivalIds.size()); festivalIds.forEach(festivalQueryInfoArtistRenewService::renewArtistInfo); - adminStageIdResolverQueryDslRepository.findStageIdsByFestivalIdIn(festivalIds) + adminStageResolverQueryDslRepository.findStageByFestivalIdIn(festivalIds) .forEach(stageQueryInfoService::renewalStageQueryInfo); } } diff --git a/backend/src/main/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepository.java b/backend/src/main/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepository.java deleted file mode 100644 index bc94976cd..000000000 --- a/backend/src/main/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.festago.admin.repository; - -import static com.festago.festival.domain.QFestival.festival; -import static com.festago.stage.domain.QStage.stage; - -import com.festago.common.querydsl.QueryDslRepositorySupport; -import com.festago.stage.domain.Stage; -import java.util.List; -import org.springframework.stereotype.Repository; - -@Repository -public class AdminStageIdResolverQueryDslRepository extends QueryDslRepositorySupport { - - public AdminStageIdResolverQueryDslRepository() { - super(Stage.class); - } - - public List findStageIdsByFestivalId(Long festivalId) { - return select(stage.id) - .from(stage) - .innerJoin(festival).on(festival.id.eq(stage.festival.id)) - .where(festival.id.eq(festivalId)) - .fetch(); - } - - public List findStageIdsByFestivalIdIn(List festivalIds) { - return select(stage.id) - .from(stage) - .innerJoin(festival).on(festival.id.eq(stage.festival.id)) - .where(festival.id.in(festivalIds)) - .fetch(); - } -} diff --git a/backend/src/main/java/com/festago/admin/repository/AdminStageResolverQueryDslRepository.java b/backend/src/main/java/com/festago/admin/repository/AdminStageResolverQueryDslRepository.java new file mode 100644 index 000000000..2364a2ceb --- /dev/null +++ b/backend/src/main/java/com/festago/admin/repository/AdminStageResolverQueryDslRepository.java @@ -0,0 +1,33 @@ +package com.festago.admin.repository; + +import static com.festago.festival.domain.QFestival.festival; +import static com.festago.stage.domain.QStage.stage; + +import com.festago.common.querydsl.QueryDslRepositorySupport; +import com.festago.stage.domain.Stage; +import java.util.List; +import org.springframework.stereotype.Repository; + +@Repository +public class AdminStageResolverQueryDslRepository extends QueryDslRepositorySupport { + + public AdminStageResolverQueryDslRepository() { + super(Stage.class); + } + + public List findStageByFestivalId(Long festivalId) { + return selectFrom(stage) + .innerJoin(stage.festival) + .leftJoin(stage.artists).fetchJoin() + .where(festival.id.eq(festivalId)) + .fetch(); + } + + public List findStageByFestivalIdIn(List festivalIds) { + return selectFrom(stage) + .innerJoin(stage.festival) + .leftJoin(stage.artists).fetchJoin() + .where(festival.id.in(festivalIds)) + .fetch(); + } +} diff --git a/backend/src/main/java/com/festago/stage/application/StageQueryInfoEventListener.java b/backend/src/main/java/com/festago/stage/application/StageQueryInfoEventListener.java index bd599b38a..88f867182 100644 --- a/backend/src/main/java/com/festago/stage/application/StageQueryInfoEventListener.java +++ b/backend/src/main/java/com/festago/stage/application/StageQueryInfoEventListener.java @@ -22,14 +22,14 @@ public class StageQueryInfoEventListener { @Transactional(propagation = Propagation.MANDATORY) public void stageCreatedEventHandler(StageCreatedEvent event) { Stage stage = event.stage(); - stageQueryInfoService.initialStageQueryInfo(stage.getId()); + stageQueryInfoService.initialStageQueryInfo(stage); } @EventListener @Transactional(propagation = Propagation.MANDATORY) public void stageUpdatedEventHandler(StageUpdatedEvent event) { Stage stage = event.stage(); - stageQueryInfoService.renewalStageQueryInfo(stage.getId()); + stageQueryInfoService.renewalStageQueryInfo(stage); } @EventListener diff --git a/backend/src/main/java/com/festago/stage/application/StageQueryInfoService.java b/backend/src/main/java/com/festago/stage/application/StageQueryInfoService.java index 3bad1f730..eb1276a48 100644 --- a/backend/src/main/java/com/festago/stage/application/StageQueryInfoService.java +++ b/backend/src/main/java/com/festago/stage/application/StageQueryInfoService.java @@ -4,13 +4,11 @@ import com.festago.artist.domain.ArtistsSerializer; import com.festago.artist.repository.ArtistRepository; import com.festago.common.exception.ErrorCode; -import com.festago.common.exception.InternalServerException; import com.festago.common.exception.NotFoundException; +import com.festago.stage.domain.Stage; import com.festago.stage.domain.StageQueryInfo; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageQueryInfoRepository; import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -23,30 +21,19 @@ public class StageQueryInfoService { private final StageQueryInfoRepository stageQueryInfoRepository; - private final StageArtistRepository stageArtistRepository; private final ArtistRepository artistRepository; private final ArtistsSerializer serializer; - public void initialStageQueryInfo(Long stageId) { - List artists = getStageArtists(stageId); - StageQueryInfo stageQueryInfo = StageQueryInfo.of(stageId, artists, serializer); + public void initialStageQueryInfo(Stage stage) { + List artists = artistRepository.findByIdIn(stage.getArtistIds()); + StageQueryInfo stageQueryInfo = StageQueryInfo.of(stage.getId(), artists, serializer); stageQueryInfoRepository.save(stageQueryInfo); } - private List getStageArtists(Long stageId) { - Set artistIds = stageArtistRepository.findAllArtistIdByStageId(stageId); - List artists = artistRepository.findByIdIn(artistIds); - if (artists.size() != artistIds.size()) { - log.error("StageArtist에 존재하지 않은 Artist가 있습니다. artistsIds=" + artistIds); - throw new InternalServerException(ErrorCode.ARTIST_NOT_FOUND); - } - return artists; - } - - public void renewalStageQueryInfo(Long stageId) { - StageQueryInfo stageQueryInfo = stageQueryInfoRepository.findByStageId(stageId) + public void renewalStageQueryInfo(Stage stage) { + StageQueryInfo stageQueryInfo = stageQueryInfoRepository.findByStageId(stage.getId()) .orElseThrow(() -> new NotFoundException(ErrorCode.STAGE_NOT_FOUND)); - List artists = getStageArtists(stageId); + List artists = artistRepository.findByIdIn(stage.getArtistIds()); stageQueryInfo.updateArtist(artists, serializer); } diff --git a/backend/src/main/java/com/festago/stage/domain/FestivalIdStageArtistsResolverImpl.java b/backend/src/main/java/com/festago/stage/domain/FestivalIdStageArtistsResolverImpl.java deleted file mode 100644 index 7a9af2170..000000000 --- a/backend/src/main/java/com/festago/stage/domain/FestivalIdStageArtistsResolverImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.festago.stage.domain; - -import com.festago.artist.domain.Artist; -import com.festago.artist.repository.ArtistRepository; -import com.festago.common.exception.ErrorCode; -import com.festago.common.exception.NotFoundException; -import com.festago.festival.domain.FestivalIdStageArtistsResolver; -import com.festago.stage.repository.StageArtistRepository; -import com.festago.stage.repository.StageRepository; -import java.util.List; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -@Component -@RequiredArgsConstructor -@Transactional(propagation = Propagation.MANDATORY) -public class FestivalIdStageArtistsResolverImpl implements FestivalIdStageArtistsResolver { - - private final StageRepository stageRepository; - private final StageArtistRepository stageArtistRepository; - private final ArtistRepository artistRepository; - - @Override - public List resolve(Long festivalId) { - List stageIds = stageRepository.findAllByFestivalId(festivalId).stream() - .map(Stage::getId) - .toList(); - Set artistIds = stageArtistRepository.findAllArtistIdByStageIdIn(stageIds); - List artists = artistRepository.findByIdIn(artistIds); - if (artists.size() != artistIds.size()) { - throw new NotFoundException(ErrorCode.FESTIVAL_NOT_FOUND); - } - return artists; - } -} diff --git a/backend/src/main/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolver.java b/backend/src/main/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolver.java new file mode 100644 index 000000000..20f7d2d7c --- /dev/null +++ b/backend/src/main/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolver.java @@ -0,0 +1,33 @@ +package com.festago.stage.infrastructure; + +import static com.festago.artist.domain.QArtist.artist; +import static com.festago.festival.domain.QFestival.festival; +import static com.festago.stage.domain.QStage.stage; +import static com.festago.stage.domain.QStageArtist.stageArtist; + +import com.festago.artist.domain.Artist; +import com.festago.common.querydsl.QueryDslHelper; +import com.festago.festival.domain.FestivalIdStageArtistsResolver; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class FestivalIdStageArtistsQueryDslResolver implements FestivalIdStageArtistsResolver { + + private final QueryDslHelper queryDslHelper; + + @Override + public List resolve(Long festivalId) { + return queryDslHelper.select(artist) + .from(festival) + .join(stage).on(stage.festival.id.eq(festival.id)) + .join(stageArtist).on(stageArtist.stageId.eq(stage.id)) + .join(artist).on(artist.id.eq(stageArtist.artistId)) + .where(festival.id.eq(festivalId)) + .orderBy(artist.id.asc()) + .distinct() + .fetch(); + } +} diff --git a/backend/src/main/java/com/festago/stage/repository/StageArtistRepository.java b/backend/src/main/java/com/festago/stage/repository/StageArtistRepository.java index 0c239b68a..c75cc22f2 100644 --- a/backend/src/main/java/com/festago/stage/repository/StageArtistRepository.java +++ b/backend/src/main/java/com/festago/stage/repository/StageArtistRepository.java @@ -1,21 +1,9 @@ package com.festago.stage.repository; import com.festago.stage.domain.StageArtist; -import java.util.List; -import java.util.Set; -import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; -import org.springframework.data.repository.query.Param; public interface StageArtistRepository extends Repository { StageArtist save(StageArtist stageArtist); - - @Query("select sa.artistId from StageArtist sa where sa.stageId = :stageId") - Set findAllArtistIdByStageId(@Param("stageId") Long stageId); - - @Query("select sa.artistId from StageArtist sa where sa.stageId in :stageIds") - Set findAllArtistIdByStageIdIn(@Param("stageIds") List stageIds); - - void deleteByStageId(Long stageId); } diff --git a/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustom.java b/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustom.java deleted file mode 100644 index d896b33fe..000000000 --- a/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustom.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.festago.stage.repository; - -import com.festago.stage.domain.Stage; -import java.util.List; -import java.util.Optional; - -public interface StageRepositoryCustom { - - List findAllDetailByFestivalId(Long festivalId); - - Optional findByIdWithFetch(Long id); -} diff --git a/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustomImpl.java b/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustomImpl.java deleted file mode 100644 index 749a34269..000000000 --- a/backend/src/main/java/com/festago/stage/repository/StageRepositoryCustomImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.festago.stage.repository; - -import static com.festago.festival.domain.QFestival.festival; -import static com.festago.school.domain.QSchool.school; -import static com.festago.stage.domain.QStage.stage; -import static com.festago.ticket.domain.QTicket.ticket; -import static com.festago.ticket.domain.QTicketAmount.ticketAmount; - -import com.festago.stage.domain.Stage; -import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; -import java.util.Optional; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class StageRepositoryCustomImpl implements StageRepositoryCustom { - - private final JPAQueryFactory queryFactory; - - @Override - public List findAllDetailByFestivalId(Long festivalId) { - return queryFactory.selectFrom(stage) - .leftJoin(stage.tickets, ticket).fetchJoin() - .leftJoin(ticket.ticketAmount, ticketAmount).fetchJoin() - .where(stage.festival.id.eq(festivalId)) - .fetch(); - } - - @Override - public Optional findByIdWithFetch(Long id) { - return Optional.ofNullable(queryFactory.selectFrom(stage) - .leftJoin(stage.festival, festival).fetchJoin() - .leftJoin(festival.school, school).fetchJoin() - .where(stage.id.eq(id)) - .fetchOne()); - } -} diff --git a/backend/src/test/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepositoryTest.java b/backend/src/test/java/com/festago/admin/repository/AdminStageResolverQueryDslRepositoryTest.java similarity index 77% rename from backend/src/test/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepositoryTest.java rename to backend/src/test/java/com/festago/admin/repository/AdminStageResolverQueryDslRepositoryTest.java index 44cff8b19..82cc9a2d1 100644 --- a/backend/src/test/java/com/festago/admin/repository/AdminStageIdResolverQueryDslRepositoryTest.java +++ b/backend/src/test/java/com/festago/admin/repository/AdminStageResolverQueryDslRepositoryTest.java @@ -23,10 +23,10 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") -class AdminStageIdResolverQueryDslRepositoryTest extends ApplicationIntegrationTest { +class AdminStageResolverQueryDslRepositoryTest extends ApplicationIntegrationTest { @Autowired - AdminStageIdResolverQueryDslRepository adminStageIdResolverQueryDslRepository; + AdminStageResolverQueryDslRepository adminStageResolverQueryDslRepository; @Autowired FestivalRepository festivalRepository; @@ -48,7 +48,7 @@ void setUp() { class findStageIdsByFestivalId { @Test - void 축제_식별자로_공연의_식별자를_모두_조회한다() { + void 축제_식별자로_공연을_모두_조회한다() { // given Festival festival = festivalRepository.save(FestivalFixture.builder().school(테코대학교).build()); List expect = IntStream.rangeClosed(1, 3) @@ -57,10 +57,12 @@ class findStageIdsByFestivalId { .toList(); // when - List actual = adminStageIdResolverQueryDslRepository.findStageIdsByFestivalId(festival.getId()); + List actual = adminStageResolverQueryDslRepository.findStageByFestivalId(festival.getId()); // then - assertThat(actual).containsExactlyInAnyOrderElementsOf(expect); + assertThat(actual) + .map(Stage::getId) + .containsExactlyInAnyOrderElementsOf(expect); } } @@ -68,7 +70,7 @@ class findStageIdsByFestivalId { class findStageIdsByFestivalIdIn { @Test - void 축제_식별자_목록으로_공연의_식별자를_모두_조회한다() { + void 축제_식별자_목록으로_공연을_모두_조회한다() { // given List festivals = IntStream.rangeClosed(1, 2) .mapToObj(i -> festivalRepository.save(FestivalFixture.builder().school(테코대학교).build())) @@ -85,10 +87,12 @@ class findStageIdsByFestivalIdIn { List festivalIds = festivals.stream() .map(Festival::getId) .toList(); - List actual = adminStageIdResolverQueryDslRepository.findStageIdsByFestivalIdIn(festivalIds); + List actual = adminStageResolverQueryDslRepository.findStageByFestivalIdIn(festivalIds); // then - assertThat(actual).containsExactlyInAnyOrderElementsOf(expect); + assertThat(actual) + .map(Stage::getId) + .containsExactlyInAnyOrderElementsOf(expect); } } } diff --git a/backend/src/test/java/com/festago/stage/application/StageQueryInfoServiceTest.java b/backend/src/test/java/com/festago/stage/application/StageQueryInfoServiceTest.java index 72e0572dd..d510e91da 100644 --- a/backend/src/test/java/com/festago/stage/application/StageQueryInfoServiceTest.java +++ b/backend/src/test/java/com/festago/stage/application/StageQueryInfoServiceTest.java @@ -9,16 +9,17 @@ import com.festago.artist.repository.ArtistRepository; import com.festago.artist.repository.MemoryArtistRepository; import com.festago.common.exception.ErrorCode; -import com.festago.common.exception.InternalServerException; import com.festago.common.exception.NotFoundException; +import com.festago.stage.domain.Stage; import com.festago.stage.domain.StageQueryInfo; -import com.festago.stage.repository.MemoryStageArtistRepository; import com.festago.stage.repository.MemoryStageQueryInfoRepository; -import com.festago.stage.repository.StageArtistRepository; +import com.festago.stage.repository.MemoryStageRepository; import com.festago.stage.repository.StageQueryInfoRepository; +import com.festago.stage.repository.StageRepository; import com.festago.support.fixture.ArtistFixture; -import com.festago.support.fixture.StageArtistFixture; +import com.festago.support.fixture.StageFixture; import com.festago.support.fixture.StageQueryInfoFixture; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -29,58 +30,45 @@ @SuppressWarnings("NonAsciiCharacters") class StageQueryInfoServiceTest { - private final Long stageId = 1L; - StageQueryInfoService stageQueryInfoService; StageQueryInfoRepository stageQueryInfoRepository; - StageArtistRepository stageArtistRepository; + StageRepository stageRepository; ArtistRepository artistRepository; ArtistsSerializer artistsSerializer = new DelimiterArtistsSerializer(","); + Stage 공연; + Artist 뉴진스; @BeforeEach void setUp() { stageQueryInfoRepository = new MemoryStageQueryInfoRepository(); - stageArtistRepository = new MemoryStageArtistRepository(); + stageRepository = new MemoryStageRepository(); artistRepository = new MemoryArtistRepository(); stageQueryInfoService = new StageQueryInfoService( stageQueryInfoRepository, - stageArtistRepository, artistRepository, artistsSerializer ); 뉴진스 = artistRepository.save(ArtistFixture.builder().name("뉴진스").build()); + 공연 = stageRepository.save(StageFixture.builder().build()); + 공연.renewArtists(List.of(뉴진스.getId())); } @Nested class initialStageQueryInfo { - @Test - void Artist가_존재하지_않으면_예외() { - // given - stageArtistRepository.save(StageArtistFixture.builder(stageId, 4885L).build()); - - // when - assertThatThrownBy(() -> stageQueryInfoService.initialStageQueryInfo(stageId)) - .isInstanceOf(InternalServerException.class) - .hasMessage(ErrorCode.ARTIST_NOT_FOUND.getMessage()); - } - @Test void StageQueryInfo가_생성된다() { - // given - stageArtistRepository.save(StageArtistFixture.builder(stageId, 뉴진스.getId()).build()); - // when - stageQueryInfoService.initialStageQueryInfo(stageId); + stageQueryInfoService.initialStageQueryInfo(공연); // then - assertThat(stageQueryInfoRepository.findByStageId(stageId)).isPresent(); + assertThat(stageQueryInfoRepository.findByStageId(공연.getId())).isPresent(); } } @@ -90,7 +78,7 @@ class renewalStageQueryInfo { @Test void Stage_식별자에_대한_StageQueryInfo가_없으면_예외() { // when & then - assertThatThrownBy(() -> stageQueryInfoService.renewalStageQueryInfo(stageId)) + assertThatThrownBy(() -> stageQueryInfoService.renewalStageQueryInfo(공연)) .isInstanceOf(NotFoundException.class) .hasMessage(ErrorCode.STAGE_NOT_FOUND.getMessage()); } @@ -99,14 +87,13 @@ class renewalStageQueryInfo { void StageQueryInfo가_새롭게_갱신된다() { // given stageQueryInfoRepository.save( - StageQueryInfoFixture.builder().stageId(stageId).artistInfo("oldInfo").build()); - stageArtistRepository.save(StageArtistFixture.builder(stageId, 뉴진스.getId()).build()); + StageQueryInfoFixture.builder().stageId(공연.getId()).artistInfo("oldInfo").build()); // when - stageQueryInfoService.renewalStageQueryInfo(stageId); + stageQueryInfoService.renewalStageQueryInfo(공연); // then - StageQueryInfo stageQueryInfo = stageQueryInfoRepository.findByStageId(stageId).get(); + StageQueryInfo stageQueryInfo = stageQueryInfoRepository.findByStageId(공연.getId()).get(); assertThat(stageQueryInfo.getArtistInfo()).isNotEqualTo("oldInfo"); } } @@ -117,13 +104,13 @@ class deleteStageQueryInfo { @Test void StageQueryInfo가_삭제된다() { // given - stageQueryInfoRepository.save(StageQueryInfoFixture.builder().stageId(stageId).build()); + stageQueryInfoRepository.save(StageQueryInfoFixture.builder().stageId(공연.getId()).build()); // when - stageQueryInfoService.deleteStageQueryInfo(stageId); + stageQueryInfoService.deleteStageQueryInfo(공연.getId()); // then - assertThat(stageQueryInfoRepository.findByStageId(stageId)).isEmpty(); + assertThat(stageQueryInfoRepository.findByStageId(공연.getId())).isEmpty(); } } } diff --git a/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java b/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java index a15c5bc86..a838e973d 100644 --- a/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java +++ b/backend/src/test/java/com/festago/stage/application/command/StageUpdateServiceTest.java @@ -14,13 +14,10 @@ import com.festago.festival.domain.Festival; import com.festago.stage.domain.Stage; import com.festago.stage.dto.command.StageUpdateCommand; -import com.festago.stage.repository.MemoryStageArtistRepository; import com.festago.stage.repository.MemoryStageRepository; -import com.festago.stage.repository.StageArtistRepository; import com.festago.stage.repository.StageRepository; import com.festago.support.fixture.ArtistFixture; import com.festago.support.fixture.FestivalFixture; -import com.festago.support.fixture.StageArtistFixture; import com.festago.support.fixture.StageFixture; import java.time.LocalDateTime; import java.util.List; @@ -38,7 +35,6 @@ class StageUpdateServiceTest { StageRepository stageRepository; ArtistRepository artistRepository; - StageArtistRepository stageArtistRepository; StageUpdateService stageUpdateService; LocalDateTime stageStartTime = LocalDateTime.parse("2077-06-30T18:00:00"); @@ -53,9 +49,11 @@ class StageUpdateServiceTest { void setUp() { stageRepository = new MemoryStageRepository(); artistRepository = new MemoryArtistRepository(); - stageArtistRepository = new MemoryStageArtistRepository(); - stageUpdateService = new StageUpdateService(stageRepository, artistRepository, - mock(ApplicationEventPublisher.class)); + stageUpdateService = new StageUpdateService( + stageRepository, + artistRepository, + mock(ApplicationEventPublisher.class) + ); 테코대학교_축제 = FestivalFixture.builder() .name("테코대학교 축제") @@ -72,9 +70,8 @@ void setUp() { 소녀시대 = artistRepository.save(ArtistFixture.builder().name("소녀시대").build()); 뉴진스 = artistRepository.save(ArtistFixture.builder().name("뉴진스").build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 에픽하이.getId()).build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 소녀시대.getId()).build()); - stageArtistRepository.save(StageArtistFixture.builder(테코대학교_축제_공연.getId(), 뉴진스.getId()).build()); + 테코대학교_축제_공연.renewArtists(List.of(에픽하이.getId())); + 테코대학교_축제_공연.renewArtists(List.of(소녀시대.getId(), 뉴진스.getId())); } @Nested diff --git a/backend/src/test/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolverTest.java b/backend/src/test/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolverTest.java new file mode 100644 index 000000000..77003cd58 --- /dev/null +++ b/backend/src/test/java/com/festago/stage/infrastructure/FestivalIdStageArtistsQueryDslResolverTest.java @@ -0,0 +1,96 @@ +package com.festago.stage.infrastructure; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.festago.artist.domain.Artist; +import com.festago.artist.repository.ArtistRepository; +import com.festago.festival.domain.Festival; +import com.festago.festival.repository.FestivalRepository; +import com.festago.school.domain.School; +import com.festago.school.repository.SchoolRepository; +import com.festago.stage.domain.Stage; +import com.festago.stage.repository.StageArtistRepository; +import com.festago.stage.repository.StageRepository; +import com.festago.support.ApplicationIntegrationTest; +import com.festago.support.fixture.ArtistFixture; +import com.festago.support.fixture.FestivalFixture; +import com.festago.support.fixture.SchoolFixture; +import com.festago.support.fixture.StageArtistFixture; +import com.festago.support.fixture.StageFixture; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class FestivalIdStageArtistsQueryDslResolverTest extends ApplicationIntegrationTest { + + @Autowired + SchoolRepository schoolRepository; + + @Autowired + FestivalRepository festivalRepository; + + @Autowired + StageRepository stageRepository; + + @Autowired + StageArtistRepository stageArtistRepository; + + @Autowired + ArtistRepository artistRepository; + + @Autowired + FestivalIdStageArtistsQueryDslResolver festivalIdStageArtistsResolver; + + Long festivalId; + + Stage 테코대학교_두번째_공연; + + Artist 뉴진스; + Artist 에픽하이; + Artist 아이유; + + @BeforeEach + void setUp() { + School 테코대학교 = schoolRepository.save(SchoolFixture.builder().name("테코대학교").build()); + 뉴진스 = artistRepository.save(ArtistFixture.builder().name("뉴진스").build()); + 에픽하이 = artistRepository.save(ArtistFixture.builder().name("에픽하이").build()); + 아이유 = artistRepository.save(ArtistFixture.builder().name("아이유").build()); + Festival 테코대학교_축제 = festivalRepository.save(FestivalFixture.builder().school(테코대학교).build()); + Stage 테코대학교_첫번째_공연 = stageRepository.save(StageFixture.builder().festival(테코대학교_축제).build()); + 테코대학교_두번째_공연 = stageRepository.save(StageFixture.builder().festival(테코대학교_축제).build()); + stageArtistRepository.save(StageArtistFixture.builder(테코대학교_첫번째_공연.getId(), 뉴진스.getId()).build()); + stageArtistRepository.save(StageArtistFixture.builder(테코대학교_두번째_공연.getId(), 에픽하이.getId()).build()); + stageArtistRepository.save(StageArtistFixture.builder(테코대학교_두번째_공연.getId(), 아이유.getId()).build()); + festivalId = 테코대학교_축제.getId(); + } + + @Test + void 축제의_식별자로_축제의_공연에_참여하는_아티스트를_모두_조회한다() { + // when + List expect = festivalIdStageArtistsResolver.resolve(festivalId); + + // then + assertThat(expect) + .map(Artist::getName) + .containsOnly(뉴진스.getName(), 에픽하이.getName(), 아이유.getName()); + } + + @Test + void 중복된_아티스트가_있으면_중복된_아티스트는_포함되지_않는다() { + // given + stageArtistRepository.save(StageArtistFixture.builder(테코대학교_두번째_공연.getId(), 아이유.getId()).build()); + + // when + List expect = festivalIdStageArtistsResolver.resolve(festivalId); + + // then + assertThat(expect) + .map(Artist::getName) + .containsOnly(뉴진스.getName(), 에픽하이.getName(), 아이유.getName()); + } +} diff --git a/backend/src/test/java/com/festago/stage/repository/MemoryStageArtistRepository.java b/backend/src/test/java/com/festago/stage/repository/MemoryStageArtistRepository.java index 3ca77f184..e068400cc 100644 --- a/backend/src/test/java/com/festago/stage/repository/MemoryStageArtistRepository.java +++ b/backend/src/test/java/com/festago/stage/repository/MemoryStageArtistRepository.java @@ -1,33 +1,9 @@ package com.festago.stage.repository; -import static java.util.stream.Collectors.toUnmodifiableSet; - import com.festago.stage.domain.StageArtist; import com.festago.support.AbstractMemoryRepository; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -public class MemoryStageArtistRepository extends AbstractMemoryRepository implements StageArtistRepository { - - @Override - public Set findAllArtistIdByStageId(Long stageId) { - return memory.values().stream() - .filter(stageArtist -> Objects.equals(stageArtist.getStageId(), stageId)) - .map(StageArtist::getArtistId) - .collect(toUnmodifiableSet()); - } - @Override - public Set findAllArtistIdByStageIdIn(List stageIds) { - return memory.values().stream() - .filter(stageArtist -> stageIds.contains(stageArtist.getStageId())) - .map(StageArtist::getArtistId) - .collect(toUnmodifiableSet()); - } +public class MemoryStageArtistRepository extends AbstractMemoryRepository implements + StageArtistRepository { - @Override - public void deleteByStageId(Long stageId) { - memory.entrySet().removeIf(entry -> Objects.equals(entry.getValue().getStageId(), stageId)); - } } diff --git a/backend/src/test/java/com/festago/stage/repository/StageRepositoryTest.java b/backend/src/test/java/com/festago/stage/repository/StageRepositoryTest.java deleted file mode 100644 index 6419a7b75..000000000 --- a/backend/src/test/java/com/festago/stage/repository/StageRepositoryTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.festago.stage.repository; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; - -import com.festago.festival.domain.Festival; -import com.festago.festival.repository.FestivalRepository; -import com.festago.school.domain.School; -import com.festago.school.repository.SchoolRepository; -import com.festago.stage.domain.Stage; -import com.festago.support.RepositoryTest; -import com.festago.support.fixture.FestivalFixture; -import com.festago.support.fixture.SchoolFixture; -import com.festago.support.fixture.StageFixture; -import com.festago.support.fixture.TicketFixture; -import com.festago.ticket.domain.Ticket; -import com.festago.ticket.domain.TicketType; -import com.festago.ticket.repository.TicketRepository; -import jakarta.persistence.EntityManager; -import java.util.List; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -@DisplayNameGeneration(ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -@RepositoryTest -class StageRepositoryTest { - - @Autowired - FestivalRepository festivalRepository; - - @Autowired - StageRepository stageRepository; - - @Autowired - TicketRepository ticketRepository; - - @Autowired - SchoolRepository schoolRepository; - - @Autowired - EntityManager entityManager; - - @Test - void 티켓이_존재하지_않을때도_무대가_조회된다() { - // given - School school = schoolRepository.save(SchoolFixture.builder().build()); - Festival festival = festivalRepository.save(FestivalFixture.builder().school(school).build()); - Stage stage1 = stageRepository.save(StageFixture.builder().festival(festival).build()); - Stage stage2 = stageRepository.save(StageFixture.builder().festival(festival).build()); - - // when - List actual = stageRepository.findAllDetailByFestivalId(festival.getId()); - - // then - List stageIds = actual.stream() - .map(Stage::getId) - .toList(); - assertThat(stageIds).containsExactlyInAnyOrder(stage1.getId(), stage2.getId()); - } - - @Test - void 해당_축제의_무대가_모두_조회된다() { - // given - School school = schoolRepository.save(SchoolFixture.builder().build()); - Festival festival = festivalRepository.save(FestivalFixture.builder().school(school).build()); - stageRepository.save(StageFixture.builder().festival(festival).build()); - - // when - List actual = stageRepository.findAllDetailByFestivalId(festival.getId()); - - // then - assertThat(actual).hasSize(1); - } - - @Test - void 티켓_정보까지_모두_조회된다() { - // given - School school = schoolRepository.save(SchoolFixture.builder().build()); - Festival festival = festivalRepository.save(FestivalFixture.builder().school(school).build()); - Stage stage = stageRepository.save(StageFixture.builder().festival(festival).build()); - Ticket ticket1 = ticketRepository.save( - TicketFixture.builder().ticketType(TicketType.STUDENT).stage(stage).build()); - Ticket ticket2 = ticketRepository.save( - TicketFixture.builder().ticketType(TicketType.VISITOR).stage(stage).build()); - ticket1.getTicketAmount().addTotalAmount(100); - ticket2.getTicketAmount().addTotalAmount(200); - entityManager.flush(); - entityManager.clear(); - - // when - List actual = stageRepository.findAllDetailByFestivalId(festival.getId()); - - // then - assertSoftly(softly -> { - softly.assertThat(actual.size()).isEqualTo(1); - Stage actualStage = actual.get(0); - softly.assertThat(actualStage.getId()).isEqualTo(stage.getId()); - List actualTickets = actualStage.getTickets(); - softly.assertThat(actualTickets.stream() - .map(Ticket::getTicketType) - .toList()) - .containsExactlyInAnyOrder(TicketType.STUDENT, TicketType.VISITOR); - softly.assertThat(actualTickets.stream() - .map(ticket -> ticket.getTicketAmount().getTotalAmount()) - .toList()) - .containsExactlyInAnyOrder(100, 200); - }); - } -}