shp 파일 생성 추가

This commit is contained in:
2025-12-26 15:42:59 +09:00
parent ef4cd48827
commit 064e4897d5
9 changed files with 381 additions and 152 deletions

View File

@@ -18,9 +18,16 @@ public class InferenceResultShpApiController {
private final InferenceResultShpService inferenceResultShpService;
@Operation(summary = "추론결과 데이터 저장", description = "추론결과 데이터 저장")
@PostMapping
public ApiResponseDto<Void> saveInferenceResultData() {
@PostMapping("/save")
public ApiResponseDto<String> saveInferenceData() {
inferenceResultShpService.saveInferenceResultData();
return ApiResponseDto.createOK(null);
return ApiResponseDto.createOK("OK");
}
@Operation(summary = "shp 파일 생성", description = "shp 파일 생성")
@PostMapping("/create")
public ApiResponseDto<String> createShpFile() {
inferenceResultShpService.createShpFile();
return ApiResponseDto.createOK("OK");
}
}

View File

@@ -1,7 +1,6 @@
package com.kamco.cd.kamcoback.inference.dto;
import com.kamco.cd.kamcoback.postgres.entity.InferenceResultEntity;
import java.time.ZonedDateTime;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
@@ -13,72 +12,55 @@ public class InferenceResultShpDto {
@Setter
public static class Basic {
private Long id;
// ===== 식별 =====
private Long geoUid;
private UUID uuid;
// ===== 그룹 키 =====
private Integer stage;
private Float cdProb;
private Integer input1;
private Integer input2;
private Long mapId;
private Integer input1; // compare_yyyy
private Integer input2; // target_yyyy
// ===== 추론 결과 =====
private Float cdProb;
private String beforeClass;
private Float beforeProbability;
private String afterClass;
private Float afterProbability;
private Float area;
private ZonedDateTime createdDttm;
private ZonedDateTime updatedDttm;
// ===== 공간 정보 =====
private Geometry geometry;
private Float area;
public Basic(
Long id,
UUID uuid,
Integer stage,
Float cdProb,
Integer input1,
Integer input2,
Long mapId,
String beforeClass,
Float beforeProbability,
String afterClass,
Float afterProbability,
Float area,
ZonedDateTime createdDttm,
ZonedDateTime updatedDttm,
Geometry geometry) {
this.id = id;
this.uuid = uuid;
this.stage = stage;
this.cdProb = cdProb;
this.input1 = input1;
this.input2 = input2;
this.mapId = mapId;
this.beforeClass = beforeClass;
this.beforeProbability = beforeProbability;
this.afterClass = afterClass;
this.afterProbability = afterProbability;
this.area = area;
this.createdDttm = createdDttm;
this.updatedDttm = updatedDttm;
this.geometry = geometry;
}
/**
* Entity → DTO 변환
*/
public static Basic from(MapSheetAnalDataInferenceGeomEntity e) {
Basic d = new Basic();
public static Basic from(InferenceResultEntity e) {
return new Basic(
e.getId(),
e.getUuid(),
e.getStage(),
e.getCdProb(),
e.getInput1(),
e.getInput2(),
e.getMapId(),
e.getBeforeClass(),
e.getBeforeProbability(),
e.getAfterClass(),
e.getAfterProbability(),
e.getArea(),
e.getCreatedDttm(),
e.getUpdatedDttm(),
e.getGeometry());
d.geoUid = e.getGeoUid();
d.uuid = e.getUuid();
d.stage = e.getStage();
d.mapId = e.getMapSheetNum();
d.input1 = e.getCompareYyyy();
d.input2 = e.getTargetYyyy();
d.cdProb = e.getCdProb();
d.beforeClass = e.getClassBeforeCd();
d.beforeProbability = e.getClassBeforeProb();
d.afterClass = e.getClassAfterCd();
d.afterProbability = e.getClassAfterProb();
d.geometry = e.getGeom();
d.area = e.getArea();
return d;
}
}
}

View File

@@ -3,7 +3,7 @@ package com.kamco.cd.kamcoback.inference.service;
import com.kamco.cd.kamcoback.inference.ShpWriter;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto;
import com.kamco.cd.kamcoback.postgres.core.InferenceResultShpCoreService;
import com.kamco.cd.kamcoback.postgres.core.InferenceResultShpCoreService.ShpKey;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -17,42 +17,66 @@ public class InferenceResultShpService {
private final InferenceResultShpCoreService coreService;
private final ShpWriter shpWriter;
/**
* inference_results -> tb_map_sheet_anal_data_inference / geom 업서트
*/
@Transactional
public void saveInferenceResultData() {
coreService.streamGrouped(
1000,
(key, entities) -> {
// Entity -> DTO
List<InferenceResultShpDto.Basic> dtoList =
entities.stream().map(InferenceResultShpDto.Basic::from).toList();
flushGroup(key, dtoList);
});
coreService.buildInferenceData();
}
/**
* 파일명 및 파일 경로
*
* @param key
* @param dtoList
* dataUid 단위로 재생성(덮어쓰기) - reset(inference false + geom 전부 false) - geom 엔티티 조회 -> dto 변환 - shp/geojson 생성 - 성공 geo_uid만 true - inference true
*/
private void flushGroup(ShpKey key, List<InferenceResultShpDto.Basic> dtoList) {
@Transactional
public void createShpFile() {
// TODO 경로 정해지면 수정해야함
// TODO 경로는 설정으로 빼는 게 좋음
String baseDir = System.getProperty("user.home") + "/export";
// 파일명 stage_input1_input2_mapId
String baseName =
String.format("%d_%d_%d_%d", key.stage(), key.mapId(), key.input1(), key.input2());
int batchSize = 100; // 한번에 처리할 data_uid 개수
int geomLimit = 500000; // data_uid 당 최대 geom 로딩 수 (메모리/시간 보고 조절)
String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이
String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson";
List<Long> dataUids = coreService.findPendingDataUids(batchSize);
// shp: .shp/.shx/.dbf 생성
shpWriter.writeShp(shpBasePath, dtoList);
for (Long dataUid : dataUids) {
// geojson: .geojson 생성
shpWriter.writeGeoJson(geoJsonPath, dtoList);
// 1) 덮어쓰기 시작: 리셋
coreService.resetForRegenerate(dataUid);
// 2) 생성 대상 조회(엔티티)
List<MapSheetAnalDataInferenceGeomEntity> entities =
coreService.loadGeomEntities(dataUid, geomLimit);
if (entities.isEmpty()) {
// 실패 상태(false 유지) -> 다음 배치에서 다시 덮어쓰기로 시도
continue;
}
// 3) 엔티티 -> DTO
List<InferenceResultShpDto.Basic> dtoList =
entities.stream().map(InferenceResultShpDto.Basic::from).toList();
// 4) 파일명: stage_mapSheet_compare_target (첫 row 기준)
MapSheetAnalDataInferenceGeomEntity first = entities.get(0);
String baseName =
String.format(
"%d_%d_%d_%d",
first.getStage(),
first.getMapSheetNum(),
first.getCompareYyyy(),
first.getTargetYyyy());
String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이
String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson";
// 5) 파일 생성 (예외 발생 시 성공 마킹 안 됨 -> 다음에 덮어쓰기 재시도)
shpWriter.writeShp(shpBasePath, dtoList);
shpWriter.writeGeoJson(geoJsonPath, dtoList);
// 6) 성공 마킹: geo_uid만 true
List<Long> geoUids = entities.stream().map(MapSheetAnalDataInferenceGeomEntity::getGeoUid).toList();
coreService.markSuccess(dataUid, geoUids);
}
}
}