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

feat-be: Process 관련 API 쿼리 최적화 #711

Merged
merged 10 commits into from
Sep 25, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.cruru.applicant.domain.dto;

import com.cruru.applicant.controller.response.ApplicantCardResponse;
import java.time.LocalDateTime;

public record ApplicantCard(
long id,

String name,

LocalDateTime createdAt,

Boolean isRejected,

long evaluationCount,

double averageScore,

long processId
) {

public ApplicantCardResponse toResponse() {
return new ApplicantCardResponse(id, name, createdAt, isRejected, (int) evaluationCount, averageScore);
}
Comment on lines +22 to +24
Copy link
Member

Choose a reason for hiding this comment

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

다른 response 변환 로직은 facade나 service에 있는데,
이 변환 로직은 여기에 두신 이유가 궁금합니다(단순 궁금).

Copy link
Member Author

@Chocochip101 Chocochip101 Sep 25, 2024

Choose a reason for hiding this comment

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

이전까지는 facade, service 계층에 dto가 없어서요...? 그리고 controller 패키지에서 도메인을 참조해서요.

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
package com.cruru.applicant.domain.repository;

import com.cruru.applicant.domain.Applicant;
import com.cruru.applicant.domain.dto.ApplicantCard;
import com.cruru.process.domain.Process;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface ApplicantRepository extends JpaRepository<Applicant, Long> {

List<Applicant> findAllByProcess(Process process);

long countByProcess(Process process);

Optional<Applicant> findByEmail(String email);
@Query("""
SELECT new com.cruru.applicant.domain.dto.ApplicantCard(
a.id, a.name, a.createdDate, a.isRejected, COUNT(e), COALESCE(AVG(e.score), 0.00), a.process.id
)
FROM Applicant a
LEFT JOIN Evaluation e ON e.applicant = a
WHERE a.process IN :processes
GROUP BY a.id, a.name, a.createdDate, a.isRejected, a.process.id
""")
List<ApplicantCard> findApplicantCardsByProcesses(@Param("processes") List<Process> processes);

@Query("""
SELECT new com.cruru.applicant.domain.dto.ApplicantCard(
a.id, a.name, a.createdDate, a.isRejected, COUNT(e), COALESCE(AVG(e.score), 0.00), a.process.id
)
FROM Applicant a
LEFT JOIN Evaluation e ON e.applicant = a
WHERE a.process = :process
GROUP BY a.id, a.name, a.createdDate, a.isRejected
""")
List<ApplicantCard> findApplicantCardsByProcess(@Param("process") Process process);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

public interface EvaluationRepository extends JpaRepository<Evaluation, Long> {

int countByApplicantAndProcess(Applicant applicant, Process process);

List<Evaluation> findAllByProcessAndApplicant(Process process, Applicant applicant);

void deleteByProcess(Process process);
void deleteByProcessId(long processId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import com.cruru.applicant.controller.request.ApplicantCreateRequest;
import com.cruru.applicant.controller.request.ApplicantMoveRequest;
import com.cruru.applicant.controller.request.ApplicantUpdateRequest;
import com.cruru.applicant.controller.response.ApplicantCardResponse;
import com.cruru.applicant.controller.response.ApplicantResponse;
import com.cruru.applicant.domain.Applicant;
import com.cruru.applicant.domain.dto.ApplicantCard;
import com.cruru.applicant.domain.repository.ApplicantRepository;
import com.cruru.applicant.exception.ApplicantNotFoundException;
import com.cruru.applicant.exception.badrequest.ApplicantRejectException;
Expand Down Expand Up @@ -95,18 +95,11 @@ public ApplicantResponse toApplicantResponse(Applicant applicant) {
);
}

public ApplicantCardResponse toApplicantCardResponse(
Applicant applicant,
int evaluationCount,
double averageScore
) {
return new ApplicantCardResponse(
applicant.getId(),
applicant.getName(),
applicant.getCreatedDate(),
applicant.isRejected(),
evaluationCount,
averageScore
);
public List<ApplicantCard> findApplicantCards(List<Process> processes) {
return applicantRepository.findApplicantCardsByProcesses(processes);
}

public List<ApplicantCard> findApplicantCards(Process process) {
return applicantRepository.findApplicantCardsByProcess(process);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ public void create(EvaluationCreateRequest request, Process process, Applicant a
evaluationRepository.save(new Evaluation(request.score(), request.content(), process, applicant));
}

public int count(Process process, Applicant applicant) {
return evaluationRepository.countByApplicantAndProcess(applicant, process);
}

public double calculateAverageScore(Process process, Applicant applicant) {
List<Evaluation> evaluations = findAllByProcessAndApplicant(process, applicant);
return evaluations.stream()
.mapToDouble(Evaluation::getScore)
.average()
.orElse(0.0);
}

public List<Evaluation> findAllByProcessAndApplicant(Process process, Applicant applicant) {
return evaluationRepository.findAllByProcessAndApplicant(process, applicant);
}
Expand All @@ -64,7 +52,7 @@ private boolean changeExists(EvaluationUpdateRequest request, Evaluation evaluat
return !(evaluation.getContent().equals(request.content()) && evaluation.getScore().equals(request.score()));
}

public void deleteByProcess(Process process) {
evaluationRepository.deleteByProcess(process);
public void deleteByProcess(long processId) {
evaluationRepository.deleteByProcessId(processId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@
import com.cruru.dashboard.domain.Dashboard;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ApplyFormRepository extends JpaRepository<ApplyForm, Long> {

Optional<ApplyForm> findByDashboard(Dashboard dashboardId);
Optional<ApplyForm> findByDashboard(Dashboard dashboard);

@Query("""
SELECT af FROM ApplyForm af
JOIN FETCH af.dashboard d
WHERE d.id = :dashboardId
""")
Optional<ApplyForm> findByDashboardId(long dashboardId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public ApplyForm findById(Long applyFormId) {
.orElseThrow(ApplyFormNotFoundException::new);
}

public ApplyForm findByDashboardId(Long dashboardId) {
return applyFormRepository.findByDashboardId(dashboardId)
.orElseThrow(ApplyFormNotFoundException::new);
}

public ApplyForm findByDashboard(Dashboard dashboard) {
return applyFormRepository.findByDashboard(dashboard)
.orElseThrow(ApplyFormNotFoundException::new);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cruru.email.controller;

import com.cruru.email.facade.EmailFacade;
import com.cruru.email.controller.dto.EmailRequest;
import com.cruru.email.facade.EmailFacade;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/java/com/cruru/email/domain/Email.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.cruru.BaseEntity;
import com.cruru.applicant.domain.Applicant;
import com.cruru.club.domain.Club;
import com.cruru.email.exception.EmailSubjectLengthException;
import com.cruru.email.exception.EmailContentLengthException;
import com.cruru.email.exception.EmailSubjectLengthException;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
Expand Down
27 changes: 13 additions & 14 deletions backend/src/main/java/com/cruru/global/util/ExceptionLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;

@Slf4j
Expand All @@ -35,13 +34,26 @@ private static void setMDC(HttpServletRequest request, CruruCustomException exce
MDC.put("exceptionMessage", exception.getMessage());
}

private static void clearMDC() {
MDC.clear();
}

// MDC 초기화
public static void info(ProblemDetail problemDetail) {
setMDC(problemDetail);
log.info("handle info level exception");
clearMDC();
}

private static void setMDC(ProblemDetail problemDetail) {
Map<String, Object> details = problemDetail.getProperties();
Map<String, String> map = new HashMap<>();
for (Entry<String, Object> stringObjectEntry : details.entrySet()) {
map.put(stringObjectEntry.getKey(), java.lang.String.valueOf(stringObjectEntry.getValue()));
}
MDC.setContextMap(map);
}

public static void warn(ProblemDetail problemDetail) {
setMDC(problemDetail);
log.warn("handle warn level exception");
Expand All @@ -53,17 +65,4 @@ public static void error(ProblemDetail problemDetail) {
log.error("handle error level exception");
clearMDC();
}

private static void setMDC(ProblemDetail problemDetail) {
Map<String, Object> details = problemDetail.getProperties();
Map<String, String> map = new HashMap<>();
for (Entry<String, Object> stringObjectEntry : details.entrySet()) {
map.put(stringObjectEntry.getKey(), java.lang.String.valueOf(stringObjectEntry.getValue()));
}
MDC.setContextMap(map);
}

private static void clearMDC() {
MDC.clear();
}
}
59 changes: 28 additions & 31 deletions backend/src/main/java/com/cruru/process/facade/ProcessFacade.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cruru.process.facade;

import com.cruru.applicant.controller.response.ApplicantCardResponse;
import com.cruru.applicant.domain.Applicant;
import com.cruru.applicant.domain.dto.ApplicantCard;
import com.cruru.applicant.service.ApplicantService;
import com.cruru.applicant.service.EvaluationService;
import com.cruru.applyform.domain.ApplyForm;
Expand Down Expand Up @@ -33,28 +33,27 @@ public class ProcessFacade {
@Transactional
public void create(ProcessCreateRequest request, long dashboardId) {
Dashboard dashboard = dashboardService.findById(dashboardId);

processService.create(request, dashboard);
}

public ProcessResponses readAllByDashboardId(long dashboardId) {
Dashboard dashboard = dashboardService.findById(dashboardId);
ApplyForm applyForm = applyFormService.findByDashboardId(dashboardId);
List<Process> processes = processService.findAllByDashboard(dashboardId);
List<ApplicantCard> applicantCards = applicantService.findApplicantCards(processes);

List<ProcessResponse> processResponses = processes.stream()
.map(process -> toProcessResponse(process, applicantCards))
.toList();

ApplyForm applyForm = applyFormService.findByDashboard(dashboard);
List<Process> processes = processService.findAllByDashboard(dashboard);
List<ProcessResponse> processResponses = toProcessResponses(processes);
return new ProcessResponses(applyForm.getId(), processResponses, applyForm.getTitle());
}

private List<ProcessResponse> toProcessResponses(List<Process> processes) {
return processes.stream()
.map(this::toProcessResponse)
private ProcessResponse toProcessResponse(Process process, List<ApplicantCard> applicantCards) {
List<ApplicantCardResponse> applicantCardResponses = applicantCards.stream()
.filter(card -> card.processId() == process.getId())
.map(ApplicantCard::toResponse)
.toList();
}

private ProcessResponse toProcessResponse(Process process) {
List<Applicant> applicantsOfProcess = applicantService.findAllByProcess(process);
List<ApplicantCardResponse> applicantCardResponses = toApplicantCardResponses(process, applicantsOfProcess);
return new ProcessResponse(
process.getId(),
process.getSequence(),
Expand All @@ -64,21 +63,6 @@ private ProcessResponse toProcessResponse(Process process) {
);
}

private List<ApplicantCardResponse> toApplicantCardResponses(
Process process,
List<Applicant> applicantsOfProcess
) {
return applicantsOfProcess.stream()
.map(applicant -> toApplicantCardResponse(process, applicant))
.toList();
}

private ApplicantCardResponse toApplicantCardResponse(Process process, Applicant applicant) {
int evaluationCount = evaluationService.count(process, applicant);
double averageScore = evaluationService.calculateAverageScore(process, applicant);
return applicantService.toApplicantCardResponse(applicant, evaluationCount, averageScore);
}

@Transactional
public ProcessResponse update(ProcessUpdateRequest request, long processId) {
Process process = processService.findById(processId);
Expand All @@ -87,11 +71,24 @@ public ProcessResponse update(ProcessUpdateRequest request, long processId) {
return toProcessResponse(process);
}

private ProcessResponse toProcessResponse(Process process) {
List<ApplicantCardResponse> applicantCardResponses = applicantService.findApplicantCards(process)
.stream()
.map(ApplicantCard::toResponse)
.toList();

return new ProcessResponse(
process.getId(),
process.getSequence(),
process.getName(),
process.getDescription(),
applicantCardResponses
);
}

@Transactional
public void delete(long processId) {
Process process = processService.findById(processId);

evaluationService.deleteByProcess(process);
evaluationService.deleteByProcess(processId);
processService.delete(processId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ private Process toEvaluateProcess(ProcessCreateRequest request, Dashboard dashbo
return new Process(request.sequence(), request.name(), request.description(), ProcessType.EVALUATE, dashboard);
}

public List<Process> findAllByDashboard(Long dashboardId) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public List<Process> findAllByDashboard(Long dashboardId) {
public List<Process> findAllByDashboardId(Long dashboardId) {

Copy link
Member Author

@Chocochip101 Chocochip101 Sep 25, 2024

Choose a reason for hiding this comment

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

다형성을 활용하기 위해 메서드명을 같게 했습니다. System.out.printlnString() 안하는 것처럼요.
혹시 어색하게 느껴지시나요?

Copy link
Member

Choose a reason for hiding this comment

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

아뇨. ㅎ ㅎ 놓치신 줄 알았습니다.
다형성이 이유라면 수정하지 않아도 될 것 같아요.

return processRepository.findAllByDashboardId(dashboardId);
}

public Process findApplyProcessOnDashboard(Dashboard dashboard) {
List<Process> processes = findAllByDashboard(dashboard);
return processes.stream()
Expand Down
Loading
Loading