From f6fba4f09fcbc00242388a6e21c80622b77559bc Mon Sep 17 00:00:00 2001 From: mindol1004 Date: Fri, 13 Dec 2024 16:59:09 +0900 Subject: [PATCH] commit --- .../com/spring/common/jpa/SpecBuilder.java | 65 +++++++++++++++++++ .../domain/schedule/api/ScheduleJobApi.java | 16 ++--- .../schedule/dto/BatchJobHistoryResponse.java | 23 +++++++ .../schedule/dto/FindJobHistoryRequest.java | 51 +++++++++++++++ .../BatchJobExecutionRepository.java | 3 +- .../service/FindJobHistoryService.java | 11 ++-- .../src/main/resources/application.yml | 2 + .../resources/static/js/apis/schedule-api.js | 7 +- .../static/js/pages/schedule/history.js | 3 +- 9 files changed, 158 insertions(+), 23 deletions(-) create mode 100644 batch-quartz/src/main/java/com/spring/common/jpa/SpecBuilder.java create mode 100644 batch-quartz/src/main/java/com/spring/domain/schedule/dto/BatchJobHistoryResponse.java create mode 100644 batch-quartz/src/main/java/com/spring/domain/schedule/dto/FindJobHistoryRequest.java diff --git a/batch-quartz/src/main/java/com/spring/common/jpa/SpecBuilder.java b/batch-quartz/src/main/java/com/spring/common/jpa/SpecBuilder.java new file mode 100644 index 0000000..1a06da3 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/common/jpa/SpecBuilder.java @@ -0,0 +1,65 @@ +package com.spring.common.jpa; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.StringUtils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class SpecBuilder { + + public static Builder builder(Class type) { + return new Builder<>(); + } + + public static class Builder { + private List> specs = new ArrayList<>(); + + private void addSpec(Specification spec) { + if (spec != null) { + specs.add(spec); + } + } + + public Builder and(Specification spec) { + addSpec(spec); + return this; + } + + public Builder ifHasText(String str, Specification spec) { + if (StringUtils.hasText(str)) { + addSpec(spec); + } + return this; + } + + public Builder ifTrue(Boolean cond, Supplier> specSupplier) { + if (cond != null && cond.booleanValue()) { + addSpec(specSupplier.get()); + } + return this; + } + + public Builder ifNotNull(V value, Function> specSupplier) { + if (value != null) { + addSpec(specSupplier.apply(value)); + } + return this; + } + + public Specification toSpec() { + Specification spec = Specification.where(null); + for (Specification s : specs) { + spec = spec.and(s); + } + return spec; + } + } + +} diff --git a/batch-quartz/src/main/java/com/spring/domain/schedule/api/ScheduleJobApi.java b/batch-quartz/src/main/java/com/spring/domain/schedule/api/ScheduleJobApi.java index 94f3932..d939a2a 100644 --- a/batch-quartz/src/main/java/com/spring/domain/schedule/api/ScheduleJobApi.java +++ b/batch-quartz/src/main/java/com/spring/domain/schedule/api/ScheduleJobApi.java @@ -1,14 +1,10 @@ package com.spring.domain.schedule.api; -import java.time.LocalDateTime; import java.util.List; import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import org.springframework.format.annotation.DateTimeFormat; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -17,7 +13,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.spring.domain.schedule.dto.BatchJobHistoryProjection; +import com.spring.domain.schedule.dto.BatchJobHistoryResponse; +import com.spring.domain.schedule.dto.FindJobHistoryRequest; import com.spring.domain.schedule.dto.ReScheduleJobRequest; import com.spring.domain.schedule.dto.ScheduleJobResponse; import com.spring.domain.schedule.service.FindJobHistoryService; @@ -30,7 +27,6 @@ import lombok.RequiredArgsConstructor; @RequestMapping("/api/schedule") @RestController @RequiredArgsConstructor -@Validated public class ScheduleJobApi { private final FindScheduleJobService findScheduleJobService; @@ -76,14 +72,12 @@ public class ScheduleJobApi { @GetMapping("/history") @PreAuthorize("hasAnyRole('SUPER', 'ADMIN')") - public List getJobHistory( - @NotNull(message = "시작일자는 필수값 입니다.") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime fromDate, - @NotNull(message = "종료일자는 필수값 입니다.") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime toDate, - @RequestParam(required = false) String jobName, + public List getJobHistory( + @Valid FindJobHistoryRequest request, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "50") int size ) { - return findJobHistoryService.getJobHistory(fromDate, toDate, jobName, page, size); + return findJobHistoryService.getJobHistory(request, page, size); } } diff --git a/batch-quartz/src/main/java/com/spring/domain/schedule/dto/BatchJobHistoryResponse.java b/batch-quartz/src/main/java/com/spring/domain/schedule/dto/BatchJobHistoryResponse.java new file mode 100644 index 0000000..6421018 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/domain/schedule/dto/BatchJobHistoryResponse.java @@ -0,0 +1,23 @@ +package com.spring.domain.schedule.dto; + +import java.time.LocalDateTime; + +import com.spring.domain.schedule.entity.BatchJobExecution; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class BatchJobHistoryResponse { + + private final String jobName; + private final LocalDateTime startTime; + private final LocalDateTime endTime; + private final String status; + + public static BatchJobHistoryResponse fromEntity(BatchJobExecution batch) { + return new BatchJobHistoryResponse(batch.getJobInstance().getJobName(), batch.getStartTime(), batch.getEndTime(), batch.getStatus()); + } + +} diff --git a/batch-quartz/src/main/java/com/spring/domain/schedule/dto/FindJobHistoryRequest.java b/batch-quartz/src/main/java/com/spring/domain/schedule/dto/FindJobHistoryRequest.java new file mode 100644 index 0000000..b93a20e --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/domain/schedule/dto/FindJobHistoryRequest.java @@ -0,0 +1,51 @@ +package com.spring.domain.schedule.dto; + +import java.time.LocalDateTime; + +import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; +import javax.validation.constraints.NotNull; + +import org.springframework.data.jpa.domain.Specification; +import org.springframework.format.annotation.DateTimeFormat; + +import com.spring.common.jpa.SpecBuilder; +import com.spring.domain.schedule.entity.BatchJobExecution; +import com.spring.domain.schedule.entity.BatchJobInstance; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class FindJobHistoryRequest { + + @NotNull(message = "시작일자는 필수값 입니다.") + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private final LocalDateTime fromDate; + + @NotNull(message = "종료일자는 필수값 입니다.") + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private final LocalDateTime toDate; + + private final String jobName; + + public Specification betweenCreateTime() { + return (root, query, builder) -> builder.between(root.get("createTime"), fromDate, toDate); + } + + public Specification equalJobName() { + return (root, query, builder) -> { + Join join = root.join("jobInstance", JoinType.INNER); + return builder.equal(join.get("jobName"), jobName); + }; + } + + public Specification toPredicate() { + return SpecBuilder.builder(BatchJobExecution.class) + .and(betweenCreateTime()) + .ifHasText(jobName, equalJobName()) + .toSpec(); + } + +} diff --git a/batch-quartz/src/main/java/com/spring/domain/schedule/repository/BatchJobExecutionRepository.java b/batch-quartz/src/main/java/com/spring/domain/schedule/repository/BatchJobExecutionRepository.java index 3171f34..3116c45 100644 --- a/batch-quartz/src/main/java/com/spring/domain/schedule/repository/BatchJobExecutionRepository.java +++ b/batch-quartz/src/main/java/com/spring/domain/schedule/repository/BatchJobExecutionRepository.java @@ -5,6 +5,7 @@ import java.util.List; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -15,7 +16,7 @@ import com.spring.domain.schedule.dto.BatchJobHourProjection; import com.spring.domain.schedule.dto.BatchJobStatusCountProjection; import com.spring.domain.schedule.entity.BatchJobExecution; -public interface BatchJobExecutionRepository extends JpaRepository { +public interface BatchJobExecutionRepository extends JpaRepository, JpaSpecificationExecutor { @Query("SELECT bji.jobName AS jobName, " + "bje.startTime AS startTime, " + diff --git a/batch-quartz/src/main/java/com/spring/domain/schedule/service/FindJobHistoryService.java b/batch-quartz/src/main/java/com/spring/domain/schedule/service/FindJobHistoryService.java index 3e829fa..f49ab2c 100644 --- a/batch-quartz/src/main/java/com/spring/domain/schedule/service/FindJobHistoryService.java +++ b/batch-quartz/src/main/java/com/spring/domain/schedule/service/FindJobHistoryService.java @@ -1,15 +1,14 @@ package com.spring.domain.schedule.service; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; -import com.spring.domain.schedule.dto.BatchJobHistoryProjection; +import com.spring.domain.schedule.dto.BatchJobHistoryResponse; +import com.spring.domain.schedule.dto.FindJobHistoryRequest; import com.spring.domain.schedule.repository.BatchJobExecutionRepository; import lombok.RequiredArgsConstructor; @@ -21,9 +20,9 @@ public class FindJobHistoryService { private final BatchJobExecutionRepository batchJobExecutionRepository; @Transactional(readOnly = true) - public List getJobHistory(LocalDateTime fromDate, LocalDateTime toDate, String jobName, int page, int size) { - return batchJobExecutionRepository.findJobHistory(fromDate, toDate, PageRequest.of(page, size)).stream() - .filter(jobHistory -> !StringUtils.hasText(jobName) || jobHistory.getJobName().equals(jobName)) + public List getJobHistory(FindJobHistoryRequest request, int page, int size) { + return batchJobExecutionRepository.findAll(request.toPredicate(), PageRequest.of(page, size)).stream() + .map(BatchJobHistoryResponse::fromEntity) .collect(Collectors.toList()); } diff --git a/batch-quartz/src/main/resources/application.yml b/batch-quartz/src/main/resources/application.yml index b7df09b..9c924a6 100644 --- a/batch-quartz/src/main/resources/application.yml +++ b/batch-quartz/src/main/resources/application.yml @@ -170,6 +170,8 @@ logging: level: root: info org: + springframework: + web: debug hibernate: SQL: debug type: diff --git a/batch-quartz/src/main/resources/static/js/apis/schedule-api.js b/batch-quartz/src/main/resources/static/js/apis/schedule-api.js index 6e709b8..c9b0fdc 100644 --- a/batch-quartz/src/main/resources/static/js/apis/schedule-api.js +++ b/batch-quartz/src/main/resources/static/js/apis/schedule-api.js @@ -41,10 +41,9 @@ const scheduleService = { return true; }, - getJobHistory: async (fromDate, toDate, jobName, page, size) => { - const response = await apiClient.get('/api/schedule/history', { - params: { fromDate, toDate, jobName, page, size } - }); + getJobHistory: async (searchParams) => { + console.log(searchParams); + const response = await apiClient.get('/api/schedule/history', { params: searchParams }); return response.data.data; } diff --git a/batch-quartz/src/main/resources/static/js/pages/schedule/history.js b/batch-quartz/src/main/resources/static/js/pages/schedule/history.js index 07bad6e..557f462 100644 --- a/batch-quartz/src/main/resources/static/js/pages/schedule/history.js +++ b/batch-quartz/src/main/resources/static/js/pages/schedule/history.js @@ -57,7 +57,8 @@ const fetchDataAndRender = async () => { const jobName = document.getElementById('jobName').value; const fromDate = dayjs(document.getElementById('fromDate').value).format('YYYY-MM-DDTHH:mm:ss'); const toDate = dayjs(document.getElementById('toDate').value).endOf('day').format('YYYY-MM-DDTHH:mm:ss'); - const jobHistories = await scheduleService.getJobHistory(fromDate, toDate, jobName, currentPage, pageSize); + const searchParams = { fromDate: fromDate, toDate: toDate, jobName: jobName, page: currentPage, size: pageSize }; + const jobHistories = await scheduleService.getJobHistory(searchParams); if (jobHistories.length > 0) { appendJobHistories(jobHistories);