commit
This commit is contained in:
@@ -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 <T> Builder<T> builder(Class<T> type) {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public static class Builder<T> {
|
||||
private List<Specification<T>> specs = new ArrayList<>();
|
||||
|
||||
private void addSpec(Specification<T> spec) {
|
||||
if (spec != null) {
|
||||
specs.add(spec);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder<T> and(Specification<T> spec) {
|
||||
addSpec(spec);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> ifHasText(String str, Specification<T> spec) {
|
||||
if (StringUtils.hasText(str)) {
|
||||
addSpec(spec);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> ifTrue(Boolean cond, Supplier<Specification<T>> specSupplier) {
|
||||
if (cond != null && cond.booleanValue()) {
|
||||
addSpec(specSupplier.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <V> Builder<T> ifNotNull(V value, Function<V, Specification<T>> specSupplier) {
|
||||
if (value != null) {
|
||||
addSpec(specSupplier.apply(value));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Specification<T> toSpec() {
|
||||
Specification<T> spec = Specification.where(null);
|
||||
for (Specification<T> s : specs) {
|
||||
spec = spec.and(s);
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<BatchJobHistoryProjection> 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<BatchJobHistoryResponse> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<BatchJobExecution> betweenCreateTime() {
|
||||
return (root, query, builder) -> builder.between(root.get("createTime"), fromDate, toDate);
|
||||
}
|
||||
|
||||
public Specification<BatchJobExecution> equalJobName() {
|
||||
return (root, query, builder) -> {
|
||||
Join<BatchJobExecution, BatchJobInstance> join = root.join("jobInstance", JoinType.INNER);
|
||||
return builder.equal(join.get("jobName"), jobName);
|
||||
};
|
||||
}
|
||||
|
||||
public Specification<BatchJobExecution> toPredicate() {
|
||||
return SpecBuilder.builder(BatchJobExecution.class)
|
||||
.and(betweenCreateTime())
|
||||
.ifHasText(jobName, equalJobName())
|
||||
.toSpec();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<BatchJobExecution, Long> {
|
||||
public interface BatchJobExecutionRepository extends JpaRepository<BatchJobExecution, Long>, JpaSpecificationExecutor<BatchJobExecution> {
|
||||
|
||||
@Query("SELECT bji.jobName AS jobName, " +
|
||||
"bje.startTime AS startTime, " +
|
||||
|
||||
@@ -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<BatchJobHistoryProjection> 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<BatchJobHistoryResponse> getJobHistory(FindJobHistoryRequest request, int page, int size) {
|
||||
return batchJobExecutionRepository.findAll(request.toPredicate(), PageRequest.of(page, size)).stream()
|
||||
.map(BatchJobHistoryResponse::fromEntity)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,8 @@ logging:
|
||||
level:
|
||||
root: info
|
||||
org:
|
||||
springframework:
|
||||
web: debug
|
||||
hibernate:
|
||||
SQL: debug
|
||||
type:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user