From 343922bc499b3ae01ada2e475e08f19bcd3fe45d Mon Sep 17 00:00:00 2001 From: Yujin1219 Date: Thu, 14 May 2026 23:37:40 +0700 Subject: [PATCH] =?UTF-8?q?refactor:=20=ED=8C=80=20=EA=B2=B0=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?N+1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/decision/dto/DecisionResponse.java | 8 +++ .../team/repository/TeamRepository.java | 16 ++++-- .../domain/team/service/TeamQueryService.java | 54 +++++++++++++------ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/whylog/server/domain/decision/dto/DecisionResponse.java b/src/main/java/com/whylog/server/domain/decision/dto/DecisionResponse.java index 68e5f95..212038b 100644 --- a/src/main/java/com/whylog/server/domain/decision/dto/DecisionResponse.java +++ b/src/main/java/com/whylog/server/domain/decision/dto/DecisionResponse.java @@ -9,6 +9,14 @@ public class DecisionResponse { + public record DecisionFlatRow( + Long decisionId, + String meetingName, + Long applicationId, + String applicationName + ) { + } + @Getter @NoArgsConstructor @AllArgsConstructor diff --git a/src/main/java/com/whylog/server/domain/team/repository/TeamRepository.java b/src/main/java/com/whylog/server/domain/team/repository/TeamRepository.java index f8b3912..592219a 100644 --- a/src/main/java/com/whylog/server/domain/team/repository/TeamRepository.java +++ b/src/main/java/com/whylog/server/domain/team/repository/TeamRepository.java @@ -1,6 +1,6 @@ package com.whylog.server.domain.team.repository; -import com.whylog.server.domain.decision.entity.Decision; +import com.whylog.server.domain.decision.dto.DecisionResponse; import com.whylog.server.domain.team.entity.Team; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -13,12 +13,18 @@ public interface TeamRepository extends JpaRepository { Boolean existsByName(String teamName); @Query(""" - SELECT DISTINCT d + SELECT new com.whylog.server.domain.decision.dto.DecisionResponse$DecisionFlatRow( + d.id, + m.name, + a.id, + a.name + ) FROM Decision d - JOIN FETCH d.meeting m - LEFT JOIN FETCH d.applications + JOIN d.meeting m + LEFT JOIN d.applications a WHERE m.team.id = :teamId + ORDER BY d.id """) - List findDecisions(@Param("teamId") Long teamId); + List findDecisionRows(@Param("teamId") Long teamId); } diff --git a/src/main/java/com/whylog/server/domain/team/service/TeamQueryService.java b/src/main/java/com/whylog/server/domain/team/service/TeamQueryService.java index 304cabd..7601a38 100644 --- a/src/main/java/com/whylog/server/domain/team/service/TeamQueryService.java +++ b/src/main/java/com/whylog/server/domain/team/service/TeamQueryService.java @@ -2,13 +2,15 @@ import com.whylog.server.domain.decision.dto.ApplicationResponse; import com.whylog.server.domain.decision.dto.DecisionResponse; -import com.whylog.server.domain.decision.entity.Decision; import com.whylog.server.domain.team.repository.TeamRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @Service @RequiredArgsConstructor @@ -19,22 +21,40 @@ public class TeamQueryService { @Transactional(readOnly = true) public List decisions( Long teamId ){ - List decisions = teamRepository.findDecisions(teamId); - - return decisions.stream() - .map(d -> DecisionResponse.DecisionListDTO.builder() - .decisionId(d.getId()) - .name(d.getMeeting().getName()) - .applications( - d.getApplications().stream() - .map(application -> ApplicationResponse.ApplicationDTO.builder() - .applicationId(application.getId()) - .name(application.getName()) - .build()) - .toList() - ) - .build() - ).toList(); + List rows = teamRepository.findDecisionRows(teamId); + Map decisions = new LinkedHashMap<>(); + + for (DecisionResponse.DecisionFlatRow row : rows) { + DecisionAccumulator decision = decisions.computeIfAbsent( + row.decisionId(), + decisionId -> new DecisionAccumulator(decisionId, row.meetingName()) + ); + + if (row.applicationId() != null) { + decision.applications().add(ApplicationResponse.ApplicationDTO.builder() + .applicationId(row.applicationId()) + .name(row.applicationName()) + .build()); + } + } + + return decisions.values().stream() + .map(decision -> DecisionResponse.DecisionListDTO.builder() + .decisionId(decision.decisionId()) + .name(decision.meetingName()) + .applications(decision.applications()) + .build()) + .toList(); + } + + private record DecisionAccumulator( + Long decisionId, + String meetingName, + List applications + ) { + private DecisionAccumulator(Long decisionId, String meetingName) { + this(decisionId, meetingName, new ArrayList<>()); + } } }