Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] Stage 생성, 수정, 삭제 시 발생하는 비효율적인 쿼리 개선 (#988) #991

Merged
merged 2 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -19,20 +19,20 @@ 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);
}

public void renewalByFestivalStartDatePeriod(LocalDate to, LocalDate end) {
List<Long> festivalIds = adminFestivalIdResolverQueryDslRepository.findFestivalIdsByStartDatePeriod(to, end);
log.info("{}개의 축제에 대해 QueryInfo를 새로 갱신합니다.", festivalIds.size());
festivalIds.forEach(festivalQueryInfoArtistRenewService::renewArtistInfo);
adminStageIdResolverQueryDslRepository.findStageIdsByFestivalIdIn(festivalIds)
adminStageResolverQueryDslRepository.findStageByFestivalIdIn(festivalIds)
.forEach(stageQueryInfoService::renewalStageQueryInfo);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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<Stage> findStageByFestivalId(Long festivalId) {
return selectFrom(stage)
.innerJoin(stage.festival)
.leftJoin(stage.artists).fetchJoin()
.where(festival.id.eq(festivalId))
.fetch();
}

public List<Stage> findStageByFestivalIdIn(List<Long> festivalIds) {
return selectFrom(stage)
.innerJoin(stage.festival)
.leftJoin(stage.artists).fetchJoin()
.where(festival.id.in(festivalIds))
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Artist> artists = getStageArtists(stageId);
StageQueryInfo stageQueryInfo = StageQueryInfo.of(stageId, artists, serializer);
public void initialStageQueryInfo(Stage stage) {
List<Artist> artists = artistRepository.findByIdIn(stage.getArtistIds());
StageQueryInfo stageQueryInfo = StageQueryInfo.of(stage.getId(), artists, serializer);
stageQueryInfoRepository.save(stageQueryInfo);
}

private List<Artist> getStageArtists(Long stageId) {
Set<Long> artistIds = stageArtistRepository.findAllArtistIdByStageId(stageId);
List<Artist> 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<Artist> artists = getStageArtists(stageId);
List<Artist> artists = artistRepository.findByIdIn(stage.getArtistIds());
stageQueryInfo.updateArtist(artists, serializer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -40,7 +37,7 @@ public Long createStage(StageCreateCommand command) {
festival
));
List<Long> artistIds = command.artistIds();
createStageArtist(artistIds, stage);
stage.renewArtists(artistIds);
eventPublisher.publishEvent(new StageCreatedEvent(stage));
return stage.getId();
}
Expand All @@ -49,12 +46,7 @@ private void validate(StageCreateCommand command) {
List<Long> artistIds = command.artistIds();
Validator.maxSize(artistIds, MAX_ARTIST_SIZE, "artistIds");
Validator.notDuplicate(artistIds, "artistIds");
}

private void createStageArtist(List<Long> 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);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -37,21 +34,16 @@ 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));
}

private void validate(StageUpdateCommand command) {
List<Long> artistIds = command.artistIds();
Validator.maxSize(artistIds, MAX_ARTIST_SIZE, "artistIds");
Validator.notDuplicate(artistIds, "artistIds");
}

private void renewStageArtist(Stage stage, List<Long> 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)));
}
}

This file was deleted.

25 changes: 24 additions & 1 deletion backend/src/main/java/com/festago/stage/domain/Stage.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -41,7 +44,8 @@ public class Stage extends BaseTimeEntity {
@OneToMany(mappedBy = "stage", fetch = FetchType.LAZY)
private List<Ticket> tickets = new ArrayList<>();

@OneToMany(fetch = FetchType.LAZY, mappedBy = "stageId")
@OneToMany(fetch = FetchType.LAZY, mappedBy = "stageId", orphanRemoval = true,
cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
private List<StageArtist> artists = new ArrayList<>();

public Stage(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) {
Expand Down Expand Up @@ -87,6 +91,25 @@ public void changeTime(LocalDateTime startTime, LocalDateTime ticketOpenTime) {
this.ticketOpenTime = ticketOpenTime;
}

public void renewArtists(List<Long> artistIds) {
artists.removeIf(artist -> !artistIds.contains(artist.getArtistId()));
Set<Long> 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<Long> getArtistIds() {
return artists.stream()
.map(StageArtist::getArtistId)
.sorted()
.toList();
}

public Long getId() {
return id;
}
Expand Down
Loading
Loading