데이터셋 API 커밋

This commit is contained in:
2026-02-03 18:51:56 +09:00
parent 19644e5c9f
commit f1ad59d0b1
13 changed files with 658 additions and 59 deletions

View File

@@ -6,21 +6,22 @@ import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum DetectionClassification { public enum DetectionClassification {
BUILDING("building", "건물", 10), ROAD("road", "도로", 10),
CONTAINER("container", "컨테이너", 20), BUILDING("building", "건물", 20),
FIELD("field", "경작지", 30), GREENHOUSE("greenhouse", "비닐하우스", 30),
FOREST("forest", "", 40), FIELD("field", "논/밭", 40),
GRASS("grass", "초지", 50), ORCHARD("orchard", "과수원", 50),
GREENHOUSE("greenhouse", "비닐하우스", 60), GRASS("grass", "초지", 60),
LAND("land", "일반토지", 70), FOREST("forest", "", 70),
ORCHARD("orchard", "과수원", 80), WATER("water", "", 80),
ROAD("road", "도로", 90), STONE("stone", "모래/자갈", 90),
STONE("stone", "모래/자갈", 100), WASTE("waste", "적치물", 100),
TANK("tank", "물탱크", 110), CONTAINER("container", "컨테이너", 110),
TUMULUS("tumulus", "토분(무덤)", 120), LAND("land", "일반토지", 120),
WASTE("waste", "폐기물", 130), SOLAR("solar", "태양광", 130),
WATER("water", "", 140), TANK("tank", "탱크", 140),
ETC("ETC", "기타", 200); // For 'etc' (miscellaneous/other) NDC("NDC", "미분류", 150),
ETC("ETC", "기타", 160);
private final String id; private final String id;
private final String desc; private final String desc;

View File

@@ -2,6 +2,8 @@ package com.kamco.cd.training.dataset;
import com.kamco.cd.training.config.api.ApiResponseDto; import com.kamco.cd.training.config.api.ApiResponseDto;
import com.kamco.cd.training.dataset.dto.DatasetDto; import com.kamco.cd.training.dataset.dto.DatasetDto;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectDataSet;
import com.kamco.cd.training.dataset.dto.DatasetObjDto;
import com.kamco.cd.training.dataset.service.DatasetService; import com.kamco.cd.training.dataset.service.DatasetService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -11,6 +13,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -39,7 +42,10 @@ public class DatasetApiController {
}) })
@GetMapping @GetMapping
public ApiResponseDto<Page<DatasetDto.Basic>> searchDatasets( public ApiResponseDto<Page<DatasetDto.Basic>> searchDatasets(
@Parameter(description = "구분", example = "DELIVER(납품), PRODUCTION(제작)") @Parameter(
description = "구분",
example = "",
schema = @Schema(allowableValues = {"DELIVER", "PRODUCTION"}))
@RequestParam(required = false) @RequestParam(required = false)
String groupTitle, String groupTitle,
@Parameter(description = "제목", example = "") @RequestParam(required = false) String title, @Parameter(description = "제목", example = "") @RequestParam(required = false) String title,
@@ -129,8 +135,7 @@ public class DatasetApiController {
return ApiResponseDto.ok(uuid); return ApiResponseDto.ok(uuid);
} }
/* @Operation(summary = "학습데이터 관리 목록 조회", description = "학습데이터 목록을 조회합니다.")
@Operation(summary = "데이터셋 통계 요약", description = "선택 데이터셋의 통계를 요약합니다.")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
@@ -139,16 +144,84 @@ public class DatasetApiController {
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = DatasetDto.Summary.class))), schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PostMapping("/summary") @GetMapping("/obj-list")
public ApiResponseDto<DatasetDto.Summary> getDatasetSummary( public ApiResponseDto<Page<DatasetObjDto.Basic>> searchDatasetObjectList(
@RequestBody @Valid DatasetDto.SummaryReq summaryReq) { @Parameter(description = "회차 uuid", example = "35e20bb2-9014-4c9d-abe2-9046db5f930c")
return ApiResponseDto.ok(datasetService.getDatasetSummary(summaryReq)); @RequestParam(required = true)
UUID uuid,
@Parameter(description = "비교년도", example = "2021") @RequestParam(required = false)
Integer compareYyyy,
@Parameter(description = "비교년도분류", example = "container") @RequestParam(required = false)
String compareClassCd,
@Parameter(description = "기준년도", example = "2022") @RequestParam(required = false)
Integer targetYyyy,
@Parameter(description = "기준년도분류", example = "waste") @RequestParam(required = false)
String targetClassCd,
@Parameter(description = "도엽번호", example = "36713060") @RequestParam(required = false)
String mapSheetNum,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
DatasetObjDto.SearchReq searchReq = new DatasetObjDto.SearchReq();
searchReq.setUuid(uuid);
searchReq.setCompareYyyy(compareYyyy);
searchReq.setCompareClassCd(compareClassCd);
searchReq.setTargetYyyy(targetYyyy);
searchReq.setTargetClassCd(targetClassCd);
searchReq.setMapSheetNum(mapSheetNum);
searchReq.setPage(page);
searchReq.setSize(size);
return ApiResponseDto.ok(datasetService.searchDatasetObjectList(searchReq));
} }
*/ @Operation(summary = "학습데이터 관리 목록 조회", description = "학습데이터 목록을 조회합니다.")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@DeleteMapping("/obj/{uuid}")
public ApiResponseDto<UUID> deleteDatasetObjByUuid(@PathVariable UUID uuid) {
return ApiResponseDto.ok(datasetService.deleteDatasetObjByUuid(uuid));
}
@Operation(summary = "학습데이터관리 상세 조회", description = "학습데이터관리 상세 정보를 조회합니다.")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = DatasetDto.Basic.class))),
@ApiResponse(responseCode = "404", description = "데이터셋을 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/select-dataset-list")
public ApiResponseDto<List<SelectDataSet>> getDatasetSelectList(
@Parameter(
description = "모델 구분",
example = "",
schema = @Schema(allowableValues = {"M1", "M2", "M3"}))
@RequestParam
String modelType,
@Parameter(
description = "선택 구분",
example = "",
schema = @Schema(allowableValues = {"CURRENT", "DELIVER", "PRODUCTION"}))
@RequestParam
String selectType) {
return ApiResponseDto.ok(datasetService.getDatasetSelectList(modelType, selectType));
}
} }

View File

@@ -1,5 +1,6 @@
package com.kamco.cd.training.dataset.dto; package com.kamco.cd.training.dataset.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.kamco.cd.training.common.enums.LearnDataRegister; import com.kamco.cd.training.common.enums.LearnDataRegister;
import com.kamco.cd.training.common.enums.LearnDataType; import com.kamco.cd.training.common.enums.LearnDataType;
import com.kamco.cd.training.common.utils.enums.Enums; import com.kamco.cd.training.common.utils.enums.Enums;
@@ -15,10 +16,12 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
@Slf4j
public class DatasetDto { public class DatasetDto {
@Schema(name = "Dataset Basic", description = "데이터셋 기본 정보") @Schema(name = "Dataset Basic", description = "데이터셋 기본 정보")
@@ -108,7 +111,7 @@ public class DatasetDto {
@AllArgsConstructor @AllArgsConstructor
public static class SearchReq { public static class SearchReq {
@Schema(description = "구분", example = "DELIVER(납품), PRODUCTION(제작)") @Schema(description = "구분")
private String groupTitle; private String groupTitle;
@Schema(description = "제목 (부분 검색)", example = "1차") @Schema(description = "제목 (부분 검색)", example = "1차")
@@ -209,4 +212,65 @@ public class DatasetDto {
@Schema(description = "평균 도엽 수", example = "750") @Schema(description = "평균 도엽 수", example = "750")
private double averageMapSheets; private double averageMapSheets;
} }
@Schema(name = "SelectDataSet", description = "데이터셋 선택 리스트")
@Getter
@Setter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class SelectDataSet {
private Long datasetId;
private UUID uuid;
private String groupTitle;
private String yyyy;
private Long roundNo;
private String memo;
private Long classCount;
private Integer buildingCount;
private Integer containerCount;
private String groupTitleCd;
public SelectDataSet(
Long datasetId,
UUID uuid,
String groupTitle,
String yyyy,
Long roundNo,
String memo,
Long classCount) {
this.datasetId = datasetId;
this.uuid = uuid;
this.groupTitle = groupTitle;
this.yyyy = yyyy;
this.roundNo = roundNo;
this.memo = memo;
this.classCount = classCount;
}
public SelectDataSet(
Long datasetId,
UUID uuid,
String groupTitle,
String yyyy,
Long roundNo,
String memo,
Integer buildingCount,
Integer containerCount) {
this.datasetId = datasetId;
this.uuid = uuid;
this.groupTitle = getGroupTitle(groupTitle);
this.groupTitleCd = groupTitle;
this.yyyy = yyyy;
this.roundNo = roundNo;
this.memo = memo;
this.buildingCount = buildingCount;
this.containerCount = containerCount;
}
public String getGroupTitle(String groupTitleCd) {
LearnDataType type = Enums.fromId(LearnDataType.class, groupTitleCd);
return type == null ? null : type.getText();
}
}
} }

View File

@@ -0,0 +1,111 @@
package com.kamco.cd.training.dataset.dto;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@Slf4j
public class DatasetObjDto {
@Schema(name = "DatasetObj Basic", description = "데이터셋 객체 Obj 기본 정보")
@Getter
@Setter
@NoArgsConstructor
public static class Basic {
private Long objId;
private Long datasetUid;
private Integer targetYyyy;
private String targetClassCd;
private Integer compareYyyy;
private String compareClassCd;
private String targetPath;
private String comparePath;
private String labelPath;
private String geojsonPath;
private String mapSheetNum;
@JsonFormatDttm private ZonedDateTime createdDttm;
private Long createdUid;
private Boolean deleted;
private UUID uuid;
public Basic(
Long objId,
Long datasetUid,
Integer targetYyyy,
String targetClassCd,
Integer compareYyyy,
String compareClassCd,
String targetPath,
String comparePath,
String labelPath,
String geojsonPath,
String mapSheetNum,
ZonedDateTime createdDttm,
Long createdUid,
Boolean deleted,
UUID uuid) {
this.objId = objId;
this.datasetUid = datasetUid;
this.targetYyyy = targetYyyy;
this.targetClassCd = targetClassCd;
this.compareYyyy = compareYyyy;
this.compareClassCd = compareClassCd;
this.targetPath = targetPath;
this.comparePath = comparePath;
this.labelPath = labelPath;
this.geojsonPath = geojsonPath;
this.mapSheetNum = mapSheetNum;
this.createdDttm = createdDttm;
this.createdUid = createdUid;
this.deleted = deleted;
this.uuid = uuid;
}
}
@Schema(name = "DatasetSearchReq", description = "데이터셋 상세 도엽목록 조회 요청")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class SearchReq {
@Schema(description = "회차 uuid", example = "35e20bb2-9014-4c9d-abe2-9046db5f930c")
private UUID uuid;
@Schema(description = "비교년도", example = "2021")
private Integer compareYyyy;
@Schema(description = "비교년도분류", example = "waste")
private String compareClassCd;
@Schema(description = "기준년도", example = "2022")
private Integer targetYyyy;
@Schema(description = "기준년도분류", example = "land")
private String targetClassCd;
@Schema(description = "도엽번호", example = "36713060")
private String mapSheetNum;
@Schema(description = "페이지 번호 (0부터 시작)", example = "0")
private int page = 0;
@Schema(description = "페이지 크기", example = "20")
private int size = 20;
public Pageable toPageable() {
// API에서는 1부터 시작하지만 내부적으로는 0부터 시작
int pageIndex = Math.max(0, page - 1);
return PageRequest.of(pageIndex, size, Sort.by(Sort.Direction.DESC, "createdDttm"));
}
}
}

View File

@@ -1,7 +1,11 @@
package com.kamco.cd.training.dataset.service; package com.kamco.cd.training.dataset.service;
import com.kamco.cd.training.dataset.dto.DatasetDto; import com.kamco.cd.training.dataset.dto.DatasetDto;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectDataSet;
import com.kamco.cd.training.dataset.dto.DatasetObjDto;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq;
import com.kamco.cd.training.postgres.core.DatasetCoreService; import com.kamco.cd.training.postgres.core.DatasetCoreService;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -83,4 +87,20 @@ public class DatasetService {
log.info("데이터셋 통계 요약 - 요청: {}", summaryReq); log.info("데이터셋 통계 요약 - 요청: {}", summaryReq);
return datasetCoreService.getDatasetSummary(summaryReq); return datasetCoreService.getDatasetSummary(summaryReq);
} }
public Page<DatasetObjDto.Basic> searchDatasetObjectList(SearchReq searchReq) {
return datasetCoreService.searchDatasetObjectList(searchReq);
}
public UUID deleteDatasetObjByUuid(UUID uuid) {
return datasetCoreService.deleteDatasetObjByUuid(uuid);
}
public List<SelectDataSet> getDatasetSelectList(String modelType, String selectType) {
if (modelType.equals("M1")) {
return datasetCoreService.getDatasetSelectM1List(modelType, selectType);
} else {
return datasetCoreService.getDatasetSelectM2M3List(modelType, selectType);
}
}
} }

View File

@@ -2,11 +2,18 @@ package com.kamco.cd.training.postgres.core;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.training.common.enums.LearnDataRegister;
import com.kamco.cd.training.common.enums.LearnDataType;
import com.kamco.cd.training.common.exception.NotFoundException; import com.kamco.cd.training.common.exception.NotFoundException;
import com.kamco.cd.training.common.service.BaseCoreService; import com.kamco.cd.training.common.service.BaseCoreService;
import com.kamco.cd.training.dataset.dto.DatasetDto; import com.kamco.cd.training.dataset.dto.DatasetDto;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectDataSet;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.Basic;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq;
import com.kamco.cd.training.model.dto.ModelMngDto; import com.kamco.cd.training.model.dto.ModelMngDto;
import com.kamco.cd.training.postgres.entity.DatasetEntity; import com.kamco.cd.training.postgres.entity.DatasetEntity;
import com.kamco.cd.training.postgres.entity.DatasetObjEntity;
import com.kamco.cd.training.postgres.repository.dataset.DatasetObjRepository;
import com.kamco.cd.training.postgres.repository.dataset.DatasetRepository; import com.kamco.cd.training.postgres.repository.dataset.DatasetRepository;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.HashMap; import java.util.HashMap;
@@ -25,6 +32,7 @@ import org.springframework.stereotype.Service;
public class DatasetCoreService public class DatasetCoreService
implements BaseCoreService<DatasetDto.Basic, Long, DatasetDto.SearchReq> { implements BaseCoreService<DatasetDto.Basic, Long, DatasetDto.SearchReq> {
private final DatasetRepository datasetRepository; private final DatasetRepository datasetRepository;
private final DatasetObjRepository datasetObjRepository;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
/** /**
@@ -99,25 +107,25 @@ public class DatasetCoreService
// 먼저 id1 필드를 임시값(0)으로 설정하여 저장 // 먼저 id1 필드를 임시값(0)으로 설정하여 저장
DatasetEntity entity = new DatasetEntity(); DatasetEntity entity = new DatasetEntity();
entity.setTitle(registerReq.getTitle()); entity.setTitle(registerReq.getTitle());
entity.setYear(registerReq.getYear()); // entity.setYear(registerReq.getYear());
entity.setGroupTitle("PRODUCTION"); entity.setGroupTitle(LearnDataType.PRODUCTION.getId());
entity.setDataYear(registerReq.getYear()); entity.setDataYear(registerReq.getYear());
entity.setRoundNo(registerReq.getRoundNo() != null ? registerReq.getRoundNo() : 1L); entity.setRoundNo(registerReq.getRoundNo() != null ? registerReq.getRoundNo() : 1L);
entity.setMemo(registerReq.getMemo()); entity.setMemo(registerReq.getMemo());
entity.setStatus("READY"); entity.setStatus(LearnDataRegister.READY.getId());
entity.setDataType("CREATE"); entity.setDataType("CREATE");
entity.setTotalItems(0L); entity.setTotalItems(0L);
entity.setTotalSize(0L); entity.setTotalSize(0L);
entity.setItemCount(0L); entity.setItemCount(0L);
entity.setDeleted(false); entity.setDeleted(false);
entity.setCreatedDttm(ZonedDateTime.now()); entity.setCreatedDttm(ZonedDateTime.now());
entity.setId1(0L); // 임시값 // entity.setId1(0L); // 임시값
DatasetEntity savedEntity = datasetRepository.save(entity); DatasetEntity savedEntity = datasetRepository.save(entity);
// 저장 후 id1을 dataset_uid와 동일하게 업데이트 // 저장 후 id1을 dataset_uid와 동일하게 업데이트
savedEntity.setId1(savedEntity.getId()); // savedEntity.setId1(savedEntity.getId());
savedEntity = datasetRepository.save(savedEntity); // savedEntity = datasetRepository.save(savedEntity);
return savedEntity.toDto(); return savedEntity.toDto();
} }
@@ -273,4 +281,27 @@ public class DatasetCoreService
double kb = size / 1024.0; double kb = size / 1024.0;
return String.format("%.2f KB", kb); return String.format("%.2f KB", kb);
} }
public Page<Basic> searchDatasetObjectList(SearchReq searchReq) {
Page<DatasetObjEntity> entityPage = datasetObjRepository.searchDatasetObjectList(searchReq);
return entityPage.map(DatasetObjEntity::toDto);
}
public UUID deleteDatasetObjByUuid(UUID uuid) {
DatasetObjEntity entity =
datasetObjRepository
.findByUuid(uuid)
.orElseThrow(() -> new NotFoundException("데이터셋 obj를 찾을 수 없습니다. ID: " + uuid));
entity.setDeleted(true);
datasetObjRepository.save(entity);
return entity.getUuid();
}
public List<SelectDataSet> getDatasetSelectM1List(String modelType, String selectType) {
return datasetRepository.getDatasetSelectM1List(modelType, selectType);
}
public List<SelectDataSet> getDatasetSelectM2M3List(String modelType, String selectType) {
return datasetRepository.getDatasetSelectM2M3List(modelType, selectType);
}
} }

View File

@@ -9,7 +9,6 @@ import jakarta.persistence.Id;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import java.time.Instant;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@@ -66,24 +65,6 @@ public class DatasetEntity {
@Column(name = "status", length = 20) @Column(name = "status", length = 20)
private String status; private String status;
@Size(max = 50)
@Column(name = "reg_user_id", length = 50)
private String regUserId;
@ColumnDefault("now()")
@Column(name = "reg_dttm")
private Instant regDttm;
@Column(name = "mod_dttm")
private Instant modDttm;
@Column(name = "id")
private Long id1;
@Size(max = 50)
@Column(name = "created_by", length = 50)
private String createdBy;
@NotNull @NotNull
@ColumnDefault("now()") @ColumnDefault("now()")
@Column(name = "created_dttm", nullable = false) @Column(name = "created_dttm", nullable = false)
@@ -101,17 +82,9 @@ public class DatasetEntity {
@Column(name = "total_items") @Column(name = "total_items")
private Long totalItems; private Long totalItems;
@Size(max = 50)
@Column(name = "updated_by", length = 50)
private String updatedBy;
@Column(name = "updated_dttm") @Column(name = "updated_dttm")
private ZonedDateTime updatedDttm; private ZonedDateTime updatedDttm;
@Size(max = 4)
@Column(name = "year", length = 4)
private String year;
@Column(name = "class_counts", columnDefinition = "jsonb") @Column(name = "class_counts", columnDefinition = "jsonb")
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
private Map<String, Integer> classCounts; private Map<String, Integer> classCounts;

View File

@@ -0,0 +1,100 @@
package com.kamco.cd.training.postgres.entity;
import com.kamco.cd.training.dataset.dto.DatasetObjDto;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
@Getter
@Setter
@Entity
@Table(name = "tb_dataset_obj")
public class DatasetObjEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "obj_id", nullable = false)
private Long objId;
@NotNull
@Column(name = "dataset_uid", nullable = false)
private Long datasetUid;
@Column(name = "target_yyyy")
private Integer targetYyyy;
@Size(max = 255)
@Column(name = "target_class_cd")
private String targetClassCd;
@Column(name = "compare_yyyy")
private Integer compareYyyy;
@Size(max = 255)
@Column(name = "compare_class_cd")
private String compareClassCd;
@Size(max = 255)
@Column(name = "target_path")
private String targetPath;
@Size(max = 255)
@Column(name = "compare_path")
private String comparePath;
@Size(max = 255)
@Column(name = "label_path")
private String labelPath;
@Size(max = 255)
@Column(name = "geojson_path")
private String geojsonPath;
@Size(max = 255)
@Column(name = "map_sheet_num")
private String mapSheetNum;
@ColumnDefault("now()")
@Column(name = "created_dttm")
private ZonedDateTime createdDttm;
@Column(name = "created_uid")
private Long createdUid;
@ColumnDefault("false")
@Column(name = "deleted")
private Boolean deleted;
@Column(name = "uuid")
private UUID uuid;
public Basic toDto() {
return new DatasetObjDto.Basic(
this.objId,
this.datasetUid,
this.targetYyyy,
this.targetClassCd,
this.compareYyyy,
this.compareClassCd,
this.targetPath,
this.comparePath,
this.labelPath,
this.geojsonPath,
this.mapSheetNum,
this.createdDttm,
this.createdUid,
this.deleted,
this.uuid);
}
}

View File

@@ -0,0 +1,7 @@
package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.postgres.entity.DatasetObjEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DatasetObjRepository
extends JpaRepository<DatasetObjEntity, Long>, DatasetObjRepositoryCustom {}

View File

@@ -0,0 +1,14 @@
package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq;
import com.kamco.cd.training.postgres.entity.DatasetObjEntity;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.domain.Page;
public interface DatasetObjRepositoryCustom {
Optional<DatasetObjEntity> findByUuid(UUID id);
Page<DatasetObjEntity> searchDatasetObjectList(SearchReq searchReq);
}

View File

@@ -0,0 +1,97 @@
package com.kamco.cd.training.postgres.repository.dataset;
import static com.kamco.cd.training.postgres.entity.QDatasetEntity.datasetEntity;
import static com.kamco.cd.training.postgres.entity.QDatasetObjEntity.datasetObjEntity;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq;
import com.kamco.cd.training.postgres.entity.DatasetEntity;
import com.kamco.cd.training.postgres.entity.DatasetObjEntity;
import com.kamco.cd.training.postgres.entity.QDatasetEntity;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityNotFoundException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor
public class DatasetObjRepositoryImpl implements DatasetObjRepositoryCustom {
private final JPAQueryFactory queryFactory;
private final QDatasetEntity dataset = datasetEntity;
@Override
public Optional<DatasetObjEntity> findByUuid(UUID id) {
return Optional.ofNullable(
queryFactory
.select(datasetObjEntity)
.from(datasetObjEntity)
.where(datasetObjEntity.uuid.eq(id), datasetObjEntity.deleted.isFalse())
.fetchOne());
}
@Override
public Page<DatasetObjEntity> searchDatasetObjectList(SearchReq searchReq) {
Pageable pageable = searchReq.toPageable();
BooleanBuilder builder = new BooleanBuilder();
if (searchReq.getCompareYyyy() != null) {
builder.and(datasetObjEntity.compareYyyy.eq(searchReq.getCompareYyyy()));
}
if (searchReq.getTargetYyyy() != null) {
builder.and(datasetObjEntity.targetYyyy.eq(searchReq.getTargetYyyy()));
}
if (StringUtils.isNotBlank(searchReq.getCompareClassCd())) {
builder.and(datasetObjEntity.compareClassCd.eq(searchReq.getCompareClassCd()));
}
if (StringUtils.isNotBlank(searchReq.getTargetClassCd())) {
builder.and(datasetObjEntity.targetClassCd.eq(searchReq.getTargetClassCd()));
}
if (StringUtils.isNotBlank(searchReq.getMapSheetNum())) {
builder.and(datasetObjEntity.mapSheetNum.eq(searchReq.getMapSheetNum()));
}
DatasetEntity entity =
queryFactory
.selectFrom(datasetEntity)
.where(datasetEntity.uuid.eq(searchReq.getUuid()))
.fetchOne();
if (Objects.isNull(entity)) {
throw new EntityNotFoundException("DatasetEntity not found for uuid: " + searchReq.getUuid());
}
List<DatasetObjEntity> content =
queryFactory
.selectFrom(datasetObjEntity)
.where(
datasetObjEntity
.deleted
.isFalse()
.and(datasetObjEntity.datasetUid.eq(entity.getId()))
.and(builder))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
// Count 쿼리 별도 실행 (null safe handling)
long total =
Optional.ofNullable(
queryFactory
.select(datasetObjEntity.count())
.from(datasetObjEntity)
.where(datasetObjEntity.deleted.isFalse().and(builder))
.fetchOne())
.orElse(0L);
return new PageImpl<>(content, pageable, total);
}
}

View File

@@ -1,7 +1,9 @@
package com.kamco.cd.training.postgres.repository.dataset; package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.dataset.dto.DatasetDto; import com.kamco.cd.training.dataset.dto.DatasetDto;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectDataSet;
import com.kamco.cd.training.postgres.entity.DatasetEntity; import com.kamco.cd.training.postgres.entity.DatasetEntity;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -10,4 +12,8 @@ public interface DatasetRepositoryCustom {
Page<DatasetEntity> findDatasetList(DatasetDto.SearchReq searchReq); Page<DatasetEntity> findDatasetList(DatasetDto.SearchReq searchReq);
Optional<DatasetEntity> findByUuid(UUID id); Optional<DatasetEntity> findByUuid(UUID id);
List<SelectDataSet> getDatasetSelectM1List(String modelType, String selectType);
List<SelectDataSet> getDatasetSelectM2M3List(String modelType, String selectType);
} }

View File

@@ -1,9 +1,15 @@
package com.kamco.cd.training.postgres.repository.dataset; package com.kamco.cd.training.postgres.repository.dataset;
import static com.kamco.cd.training.postgres.entity.QDatasetObjEntity.datasetObjEntity;
import com.kamco.cd.training.dataset.dto.DatasetDto; import com.kamco.cd.training.dataset.dto.DatasetDto;
import com.kamco.cd.training.dataset.dto.DatasetDto.SelectDataSet;
import com.kamco.cd.training.postgres.entity.DatasetEntity; import com.kamco.cd.training.postgres.entity.DatasetEntity;
import com.kamco.cd.training.postgres.entity.QDatasetEntity; import com.kamco.cd.training.postgres.entity.QDatasetEntity;
import com.querydsl.core.BooleanBuilder; import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.jpa.impl.JPAQueryFactory; import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@@ -72,4 +78,100 @@ public class DatasetRepositoryImpl implements DatasetRepositoryCustom {
.where(dataset.uuid.eq(id), dataset.deleted.isFalse()) .where(dataset.uuid.eq(id), dataset.deleted.isFalse())
.fetchOne()); .fetchOne());
} }
@Override
public List<SelectDataSet> getDatasetSelectM1List(String modelType, String selectType) {
BooleanBuilder builder = new BooleanBuilder();
if (StringUtils.isNotBlank(selectType) && !"CURRENT".equals(selectType)) {
builder.and(dataset.groupTitle.eq(selectType));
}
return queryFactory
.select(
Projections.constructor(
SelectDataSet.class,
dataset.id,
dataset.uuid,
dataset.groupTitle,
dataset.title,
dataset.roundNo,
dataset.memo,
new CaseBuilder()
.when(datasetObjEntity.targetClassCd.eq("building"))
.then(1)
.otherwise(0)
.sum(),
new CaseBuilder()
.when(datasetObjEntity.targetClassCd.eq("container"))
.then(1)
.otherwise(0)
.sum()))
.from(dataset)
.leftJoin(datasetObjEntity)
.on(dataset.id.eq(datasetObjEntity.datasetUid))
.where(builder) // datasetObjEntity.targetClassCd.in("building", "container").and(
.groupBy(
dataset.id,
dataset.uuid,
dataset.groupTitle,
dataset.title,
dataset.roundNo,
dataset.memo)
.orderBy(dataset.createdDttm.desc())
.fetch();
}
@Override
public List<SelectDataSet> getDatasetSelectM2M3List(String modelType, String selectType) {
BooleanBuilder builder = new BooleanBuilder();
NumberExpression<Long> selectedCnt;
NumberExpression<Long> wasteCnt =
datasetObjEntity.targetClassCd.when("waste").then(1L).otherwise(0L).sum();
NumberExpression<Long> elseCnt =
new CaseBuilder()
.when(datasetObjEntity.targetClassCd.notIn("building", "container", "waste"))
.then(1L)
.otherwise(0L)
.sum();
if (modelType.equals("M2")) {
selectedCnt = wasteCnt;
} else {
selectedCnt = elseCnt;
}
if (StringUtils.isNotBlank(selectType) && !"CURRENT".equals(selectType)) {
builder.and(dataset.groupTitle.eq(selectType));
}
return queryFactory
.select(
Projections.constructor(
SelectDataSet.class,
dataset.id,
dataset.uuid,
dataset.groupTitle,
dataset.title,
dataset.roundNo,
dataset.memo,
selectedCnt.as("cnt")))
.from(dataset)
.leftJoin(datasetObjEntity)
.on(dataset.id.eq(datasetObjEntity.datasetUid))
.where(builder)
.groupBy(
dataset.id,
dataset.uuid,
dataset.groupTitle,
dataset.title,
dataset.roundNo,
dataset.memo)
.orderBy(dataset.createdDttm.desc())
.fetch();
}
} }