List<Tuple> 참조 해제 적용하기

This commit is contained in:
2025-12-01 14:24:41 +09:00
parent d08e2c6e25
commit 94ea935317
2 changed files with 206 additions and 194 deletions

View File

@@ -40,128 +40,129 @@ public class InferenceResultApiController {
@Operation(summary = "추론관리 분석결과 목록 조회", description = "분석상태, 제목으로 분석결과를 조회 합니다.") @Operation(summary = "추론관리 분석결과 목록 조회", description = "분석상태, 제목으로 분석결과를 조회 합니다.")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Page.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)
}) })
@GetMapping("/list") @GetMapping("/list")
public ApiResponseDto<Page<InferenceResultDto.AnalResList>> getInferenceResultList( public ApiResponseDto<Page<InferenceResultDto.AnalResList>> getInferenceResultList(
@Parameter(description = "분석상태", example = "0002") @RequestParam(required = false) @Parameter(description = "분석상태", example = "0002") @RequestParam(required = false)
String statCode, String statCode,
@Parameter(description = "제목", example = "변화탐지") @RequestParam(required = false) String title, @Parameter(description = "제목", example = "변화탐지") @RequestParam(required = false) String title,
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0")
int page, int page,
@Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20")
int size, int size,
@Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc")
@RequestParam(required = false) @RequestParam(required = false)
String sort) { String sort) {
InferenceResultDto.SearchReq searchReq = InferenceResultDto.SearchReq searchReq =
new InferenceResultDto.SearchReq(statCode, title, page, size, sort); new InferenceResultDto.SearchReq(statCode, title, page, size, sort);
Page<InferenceResultDto.AnalResList> analResList = Page<InferenceResultDto.AnalResList> analResList =
inferenceResultService.getInferenceResultList(searchReq); inferenceResultService.getInferenceResultList(searchReq);
return ApiResponseDto.ok(analResList); return ApiResponseDto.ok(analResList);
} }
@Operation(summary = "추론관리 분석결과 요약정보", description = "분석결과 요약정보를 조회합니다.") @Operation(summary = "추론관리 분석결과 요약정보", description = "분석결과 요약정보를 조회합니다.")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = InferenceResultDto.AnalResSummary.class))), schema = @Schema(implementation = InferenceResultDto.AnalResSummary.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)
}) })
@GetMapping("/summary/{id}") @GetMapping("/summary/{id}")
public ApiResponseDto<InferenceResultDto.AnalResSummary> getInferenceResultSummary( public ApiResponseDto<InferenceResultDto.AnalResSummary> getInferenceResultSummary(
@Parameter(description = "목록 id", example = "1") @PathVariable Long id) { @Parameter(description = "목록 id", example = "1") @PathVariable Long id) {
return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id)); return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id));
} }
@Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard") @Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = InferenceResultDto.Detail.class))), schema = @Schema(implementation = InferenceResultDto.Detail.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)
}) })
@GetMapping("/detail/{id}") @GetMapping("/detail/{id}")
public ApiResponseDto<InferenceResultDto.Detail> getInferenceDetail( public ApiResponseDto<InferenceResultDto.Detail> getInferenceDetail(
@Parameter(description = "목록 id", example = "1") @PathVariable Long id) { @Parameter(description = "목록 id", example = "1") @PathVariable Long id) {
return ApiResponseDto.ok(inferenceResultService.getDetail(id)); return ApiResponseDto.ok(inferenceResultService.getDetail(id));
} }
@Operation(summary = "추론관리 분석결과 상세 목록", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회") @Operation(summary = "추론관리 분석결과 상세 목록", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Page.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)
}) })
@GetMapping("/geom/{id}") @GetMapping("/geom/{id}")
public ApiResponseDto<Page<InferenceResultDto.Geom>> getInferenceResultGeomList( public ApiResponseDto<Page<InferenceResultDto.Geom>> getInferenceResultGeomList(
@Parameter(description = "분석결과 id", example = "1") @PathVariable Long id, @Parameter(description = "분석결과 id", example = "1") @PathVariable Long id,
@Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false) @Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false)
String targetClass, String targetClass,
@Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false) @Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false)
String compareClass, String compareClass,
@Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false)
List<Long> mapSheetNum, List<Long> mapSheetNum,
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0")
int page, int page,
@Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20")
int size, int size,
@Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc")
@RequestParam(required = false) @RequestParam(required = false)
String sort) { String sort) {
InferenceResultDto.SearchGeoReq searchGeoReq = InferenceResultDto.SearchGeoReq searchGeoReq =
new InferenceResultDto.SearchGeoReq( new InferenceResultDto.SearchGeoReq(
targetClass, compareClass, mapSheetNum, page, size, sort); targetClass, compareClass, mapSheetNum, page, size, sort);
Page<InferenceResultDto.Geom> geomList = Page<InferenceResultDto.Geom> geomList =
inferenceResultService.getInferenceResultGeomList(id, searchGeoReq); inferenceResultService.getInferenceResultGeomList(id, searchGeoReq);
return ApiResponseDto.ok(geomList); return ApiResponseDto.ok(geomList);
} }
// @Operation(summary = "학습모델 결과 처리", description = "실제 학습모델 GeoJSON 파일을 처리하여 데이터베이스에 저장합니다.") // @Operation(summary = "학습모델 결과 처리", description = "실제 학습모델 GeoJSON 파일을 처리하여 데이터베이스에 저장합니다.")
// @ApiResponses( // @ApiResponses(
// value = { // value = {
// @ApiResponse( // @ApiResponse(
// responseCode = "200", // responseCode = "200",
// description = "처리 성공", // description = "처리 성공",
// content = // content =
// @Content( // @Content(
// mediaType = "application/json", // mediaType = "application/json",
// schema = // schema =
// @Schema(implementation = LearningModelResultDto.ProcessResponse.class))), // @Schema(implementation =
// @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), // LearningModelResultDto.ProcessResponse.class))),
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) // @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content),
// }) // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
// @PostMapping("/learning-model/process") // })
// @PostMapping("/learning-model/process")
public ApiResponseDto<LearningModelResultDto.ProcessResponse> processLearningModelResult( public ApiResponseDto<LearningModelResultDto.ProcessResponse> processLearningModelResult(
@RequestBody LearningModelResultDto.ProcessRequest request) { @RequestBody LearningModelResultDto.ProcessRequest request) {
try { try {
logger.info("Processing learning model result file: {}", request.getFilePath()); logger.info("Processing learning model result file: {}", request.getFilePath());
@@ -169,53 +170,55 @@ public class InferenceResultApiController {
int processedFeatures = learningModelResultProcessor.processLearningModelResult(filePath); int processedFeatures = learningModelResultProcessor.processLearningModelResult(filePath);
LearningModelResultDto.ProcessResponse response = LearningModelResultDto.ProcessResponse response =
LearningModelResultDto.ProcessResponse.builder() LearningModelResultDto.ProcessResponse.builder()
.success(true) .success(true)
.message("학습모델 결과 처리가 완료되었습니다.") .message("학습모델 결과 처리가 완료되었습니다.")
.processedFeatures(processedFeatures) .processedFeatures(processedFeatures)
.filePath(request.getFilePath()) .filePath(request.getFilePath())
.build(); .build();
logger.info( logger.info(
"Successfully processed {} features from file: {}", "Successfully processed {} features from file: {}",
processedFeatures, processedFeatures,
request.getFilePath()); request.getFilePath());
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to process learning model result: {}", request.getFilePath(), e); logger.error("Failed to process learning model result: {}", request.getFilePath(), e);
LearningModelResultDto.ProcessResponse response = LearningModelResultDto.ProcessResponse response =
LearningModelResultDto.ProcessResponse.builder() LearningModelResultDto.ProcessResponse.builder()
.success(false) .success(false)
.message("학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) .message("학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage())
.processedFeatures(0) .processedFeatures(0)
.filePath(request.getFilePath()) .filePath(request.getFilePath())
.build(); .build();
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} }
} }
// @Operation(summary = "학습모델 결과 일괄 처리", description = "여러 학습모델 GeoJSON 파일을 일괄 처리하여 데이터베이스에 저장합니다.") // @Operation(summary = "학습모델 결과 일괄 처리", description = "여러 학습모델 GeoJSON 파일을 일괄 처리하여 데이터베이스에
// @ApiResponses( // 저장합니다.")
// value = { // @ApiResponses(
// @ApiResponse( // value = {
// responseCode = "200", // @ApiResponse(
// description = "처리 성공", // responseCode = "200",
// content = // description = "처리 성공",
// @Content( // content =
// mediaType = "application/json", // @Content(
// schema = // mediaType = "application/json",
// @Schema( // schema =
// implementation = LearningModelResultDto.BatchProcessResponse.class))), // @Schema(
// @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), // implementation =
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) // LearningModelResultDto.BatchProcessResponse.class))),
// }) // @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content),
// @PostMapping("/learning-model/process-batch") // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
// })
// @PostMapping("/learning-model/process-batch")
public ApiResponseDto<LearningModelResultDto.BatchProcessResponse> public ApiResponseDto<LearningModelResultDto.BatchProcessResponse>
processBatchLearningModelResults( processBatchLearningModelResults(
@RequestBody LearningModelResultDto.BatchProcessRequest request) { @RequestBody LearningModelResultDto.BatchProcessRequest request) {
try { try {
logger.info("Processing {} learning model result files", request.getFilePaths().size()); logger.info("Processing {} learning model result files", request.getFilePaths().size());
@@ -225,64 +228,65 @@ public class InferenceResultApiController {
} }
int totalProcessedFeatures = int totalProcessedFeatures =
learningModelResultProcessor.processMultipleLearningModelResults(filePaths); learningModelResultProcessor.processMultipleLearningModelResults(filePaths);
LearningModelResultDto.BatchProcessResponse response = LearningModelResultDto.BatchProcessResponse response =
LearningModelResultDto.BatchProcessResponse.builder() LearningModelResultDto.BatchProcessResponse.builder()
.success(true) .success(true)
.message("일괄 학습모델 결과 처리가 완료되었습니다.") .message("일괄 학습모델 결과 처리가 완료되었습니다.")
.totalProcessedFeatures(totalProcessedFeatures) .totalProcessedFeatures(totalProcessedFeatures)
.processedFileCount(request.getFilePaths().size()) .processedFileCount(request.getFilePaths().size())
.filePaths(request.getFilePaths()) .filePaths(request.getFilePaths())
.build(); .build();
logger.info( logger.info(
"Successfully processed {} features from {} files", "Successfully processed {} features from {} files",
totalProcessedFeatures, totalProcessedFeatures,
request.getFilePaths().size()); request.getFilePaths().size());
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to process batch learning model results", e); logger.error("Failed to process batch learning model results", e);
LearningModelResultDto.BatchProcessResponse response = LearningModelResultDto.BatchProcessResponse response =
LearningModelResultDto.BatchProcessResponse.builder() LearningModelResultDto.BatchProcessResponse.builder()
.success(false) .success(false)
.message("일괄 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) .message("일괄 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage())
.totalProcessedFeatures(0) .totalProcessedFeatures(0)
.processedFileCount(0) .processedFileCount(0)
.filePaths(request.getFilePaths()) .filePaths(request.getFilePaths())
.build(); .build();
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} }
} }
// @Operation(summary = "기본 학습모델 파일 처리", description = "미리 준비된 학습모델 파일을 처리합니다.") // @Operation(summary = "기본 학습모델 파일 처리", description = "미리 준비된 학습모델 파일을 처리합니다.")
// @ApiResponses( // @ApiResponses(
// value = { // value = {
// @ApiResponse( // @ApiResponse(
// responseCode = "200", // responseCode = "200",
// description = "처리 성공", // description = "처리 성공",
// content = // content =
// @Content( // @Content(
// mediaType = "application/json", // mediaType = "application/json",
// schema = // schema =
// @Schema( // @Schema(
// implementation = LearningModelResultDto.BatchProcessResponse.class))), // implementation =
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) // LearningModelResultDto.BatchProcessResponse.class))),
// }) // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
// @PostMapping("/learning-model/process-default") // })
// @PostMapping("/learning-model/process-default")
public ApiResponseDto<LearningModelResultDto.BatchProcessResponse> public ApiResponseDto<LearningModelResultDto.BatchProcessResponse>
processDefaultLearningModelResults() { processDefaultLearningModelResults() {
try { try {
logger.info("Processing default learning model result files"); logger.info("Processing default learning model result files");
// Process the two default learning model files from upload directory // Process the two default learning model files from upload directory
List<String> defaultFilePaths = List<String> defaultFilePaths =
List.of( List.of(
"/Users/deniallee/geojson/upload/캠코_2021_2022_35813023.geojson", "/Users/deniallee/geojson/upload/캠코_2021_2022_35813023.geojson",
"/Users/deniallee/geojson/upload/캠코_2023_2024_35810049.geojson"); "/Users/deniallee/geojson/upload/캠코_2023_2024_35810049.geojson");
List<Path> filePaths = new ArrayList<>(); List<Path> filePaths = new ArrayList<>();
for (String filePath : defaultFilePaths) { for (String filePath : defaultFilePaths) {
@@ -290,34 +294,34 @@ public class InferenceResultApiController {
} }
int totalProcessedFeatures = int totalProcessedFeatures =
learningModelResultProcessor.processMultipleLearningModelResults(filePaths); learningModelResultProcessor.processMultipleLearningModelResults(filePaths);
LearningModelResultDto.BatchProcessResponse response = LearningModelResultDto.BatchProcessResponse response =
LearningModelResultDto.BatchProcessResponse.builder() LearningModelResultDto.BatchProcessResponse.builder()
.success(true) .success(true)
.message("기본 학습모델 결과 파일 처리가 완료되었습니다.") .message("기본 학습모델 결과 파일 처리가 완료되었습니다.")
.totalProcessedFeatures(totalProcessedFeatures) .totalProcessedFeatures(totalProcessedFeatures)
.processedFileCount(defaultFilePaths.size()) .processedFileCount(defaultFilePaths.size())
.filePaths(defaultFilePaths) .filePaths(defaultFilePaths)
.build(); .build();
logger.info( logger.info(
"Successfully processed {} features from {} default files", "Successfully processed {} features from {} default files",
totalProcessedFeatures, totalProcessedFeatures,
defaultFilePaths.size()); defaultFilePaths.size());
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to process default learning model results", e); logger.error("Failed to process default learning model results", e);
LearningModelResultDto.BatchProcessResponse response = LearningModelResultDto.BatchProcessResponse response =
LearningModelResultDto.BatchProcessResponse.builder() LearningModelResultDto.BatchProcessResponse.builder()
.success(false) .success(false)
.message("기본 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) .message("기본 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage())
.totalProcessedFeatures(0) .totalProcessedFeatures(0)
.processedFileCount(0) .processedFileCount(0)
.filePaths(List.of()) .filePaths(List.of())
.build(); .build();
return ApiResponseDto.ok(response); return ApiResponseDto.ok(response);
} }

View File

@@ -171,6 +171,9 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport
ChangeDetectionDto.PolygonFeatureList polygonList = new ChangeDetectionDto.PolygonFeatureList(); ChangeDetectionDto.PolygonFeatureList polygonList = new ChangeDetectionDto.PolygonFeatureList();
polygonList.setType("FeatureCollection"); polygonList.setType("FeatureCollection");
polygonList.setFeatures(result); polygonList.setFeatures(result);
list.clear(); // List<Tuple> 사용 참조 해제
return polygonList; return polygonList;
} }
@@ -194,25 +197,30 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport
.fetch(); .fetch();
GeoJsonReader reader = new GeoJsonReader(); GeoJsonReader reader = new GeoJsonReader();
return list.stream() List<ChangeDetectionDto.PointFeature> result =
.map( list.stream()
tuple -> { .map(
String geojson = tuple.get(0, String.class); tuple -> {
Geometry geom; String geojson = tuple.get(0, String.class);
try { Geometry geom;
geom = reader.read(geojson); try {
} catch (Exception ex) { geom = reader.read(geojson);
throw new RuntimeException("GeoJSON -> Geometry 변환 실패", ex); } catch (Exception ex) {
} throw new RuntimeException("GeoJSON -> Geometry 변환 실패", ex);
}
Long geoUid = tuple.get(mapSheetAnalDataGeomEntity.id).longValue(); Long geoUid = tuple.get(mapSheetAnalDataGeomEntity.id).longValue();
String classCd = String classCd =
tuple.get(mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase()).toString(); tuple.get(mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase()).toString();
return new ChangeDetectionDto.PointFeature( return new ChangeDetectionDto.PointFeature(
"Feature", geom, new ChangeDetectionDto.PointProperties(geoUid, classCd)); "Feature", geom, new ChangeDetectionDto.PointProperties(geoUid, classCd));
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
list.clear(); // List<Tuple> 사용 참조 해제
return result;
} }
@Override @Override