shp 파일 생성 추가

This commit is contained in:
2025-12-26 15:43:08 +09:00
parent 064e4897d5
commit 2a60ddfd36
4 changed files with 76 additions and 83 deletions

View File

@@ -19,8 +19,8 @@ public class InferenceResultShpDto {
// ===== 그룹 키 ===== // ===== 그룹 키 =====
private Integer stage; private Integer stage;
private Long mapId; private Long mapId;
private Integer input1; // compare_yyyy private Integer input1; // compare_yyyy
private Integer input2; // target_yyyy private Integer input2; // target_yyyy
// ===== 추론 결과 ===== // ===== 추론 결과 =====
private Float cdProb; private Float cdProb;
@@ -35,9 +35,7 @@ public class InferenceResultShpDto {
private Geometry geometry; private Geometry geometry;
private Float area; private Float area;
/** /** Entity → DTO 변환 */
* Entity → DTO 변환
*/
public static Basic from(MapSheetAnalDataInferenceGeomEntity e) { public static Basic from(MapSheetAnalDataInferenceGeomEntity e) {
Basic d = new Basic(); Basic d = new Basic();

View File

@@ -17,16 +17,15 @@ public class InferenceResultShpService {
private final InferenceResultShpCoreService coreService; private final InferenceResultShpCoreService coreService;
private final ShpWriter shpWriter; private final ShpWriter shpWriter;
/** /** inference_results -> tb_map_sheet_anal_data_inference / geom 업서트 */
* inference_results -> tb_map_sheet_anal_data_inference / geom 업서트
*/
@Transactional @Transactional
public void saveInferenceResultData() { public void saveInferenceResultData() {
coreService.buildInferenceData(); coreService.buildInferenceData();
} }
/** /**
* dataUid 단위로 재생성(덮어쓰기) - reset(inference false + geom 전부 false) - geom 엔티티 조회 -> dto 변환 - shp/geojson 생성 - 성공 geo_uid만 true - inference true * dataUid 단위로 재생성(덮어쓰기) - reset(inference false + geom 전부 false) - geom 엔티티 조회 -> dto 변환 -
* shp/geojson 생성 - 성공 geo_uid만 true - inference true
*/ */
@Transactional @Transactional
public void createShpFile() { public void createShpFile() {
@@ -34,8 +33,8 @@ public class InferenceResultShpService {
// TODO 경로는 설정으로 빼는 게 좋음 // TODO 경로는 설정으로 빼는 게 좋음
String baseDir = System.getProperty("user.home") + "/export"; String baseDir = System.getProperty("user.home") + "/export";
int batchSize = 100; // 한번에 처리할 data_uid 개수 int batchSize = 100; // 한번에 처리할 data_uid 개수
int geomLimit = 500000; // data_uid 당 최대 geom 로딩 수 (메모리/시간 보고 조절) int geomLimit = 500000; // data_uid 당 최대 geom 로딩 수 (메모리/시간 보고 조절)
List<Long> dataUids = coreService.findPendingDataUids(batchSize); List<Long> dataUids = coreService.findPendingDataUids(batchSize);
@@ -46,7 +45,7 @@ public class InferenceResultShpService {
// 2) 생성 대상 조회(엔티티) // 2) 생성 대상 조회(엔티티)
List<MapSheetAnalDataInferenceGeomEntity> entities = List<MapSheetAnalDataInferenceGeomEntity> entities =
coreService.loadGeomEntities(dataUid, geomLimit); coreService.loadGeomEntities(dataUid, geomLimit);
if (entities.isEmpty()) { if (entities.isEmpty()) {
// 실패 상태(false 유지) -> 다음 배치에서 다시 덮어쓰기로 시도 // 실패 상태(false 유지) -> 다음 배치에서 다시 덮어쓰기로 시도
@@ -55,19 +54,19 @@ public class InferenceResultShpService {
// 3) 엔티티 -> DTO // 3) 엔티티 -> DTO
List<InferenceResultShpDto.Basic> dtoList = List<InferenceResultShpDto.Basic> dtoList =
entities.stream().map(InferenceResultShpDto.Basic::from).toList(); entities.stream().map(InferenceResultShpDto.Basic::from).toList();
// 4) 파일명: stage_mapSheet_compare_target (첫 row 기준) // 4) 파일명: stage_mapSheet_compare_target (첫 row 기준)
MapSheetAnalDataInferenceGeomEntity first = entities.get(0); MapSheetAnalDataInferenceGeomEntity first = entities.get(0);
String baseName = String baseName =
String.format( String.format(
"%d_%d_%d_%d", "%d_%d_%d_%d",
first.getStage(), first.getStage(),
first.getMapSheetNum(), first.getMapSheetNum(),
first.getCompareYyyy(), first.getCompareYyyy(),
first.getTargetYyyy()); first.getTargetYyyy());
String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이 String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이
String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson"; String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson";
// 5) 파일 생성 (예외 발생 시 성공 마킹 안 됨 -> 다음에 덮어쓰기 재시도) // 5) 파일 생성 (예외 발생 시 성공 마킹 안 됨 -> 다음에 덮어쓰기 재시도)
@@ -75,7 +74,8 @@ public class InferenceResultShpService {
shpWriter.writeGeoJson(geoJsonPath, dtoList); shpWriter.writeGeoJson(geoJsonPath, dtoList);
// 6) 성공 마킹: geo_uid만 true // 6) 성공 마킹: geo_uid만 true
List<Long> geoUids = entities.stream().map(MapSheetAnalDataInferenceGeomEntity::getGeoUid).toList(); List<Long> geoUids =
entities.stream().map(MapSheetAnalDataInferenceGeomEntity::getGeoUid).toList();
coreService.markSuccess(dataUid, geoUids); coreService.markSuccess(dataUid, geoUids);
} }
} }

View File

@@ -13,25 +13,22 @@ public class InferenceResultShpCoreService {
private final InferenceResultRepository repo; private final InferenceResultRepository repo;
/** /** inference_results -> (inference, geom) upsert */
* inference_results -> (inference, geom) upsert
*/
@Transactional @Transactional
public void buildInferenceData() { public void buildInferenceData() {
repo.upsertGroupsFromInferenceResults(); repo.upsertGroupsFromInferenceResults();
repo.upsertGeomsFromInferenceResults(); repo.upsertGeomsFromInferenceResults();
} }
/** /** file_created_yn = false/null 인 data_uid 목록 */
* file_created_yn = false/null 인 data_uid 목록
*/
@Transactional(readOnly = true) @Transactional(readOnly = true)
public List<Long> findPendingDataUids(int limit) { public List<Long> findPendingDataUids(int limit) {
return repo.findPendingDataUids(limit); return repo.findPendingDataUids(limit);
} }
/** /**
* 재생성 시작: 덮어쓰기 기준(무조건 처음부터) - inference.file_created_yn = false, file_created_dttm = null - geom(file_created_yn) 전부 false 리셋 * 재생성 시작: 덮어쓰기 기준(무조건 처음부터) - inference.file_created_yn = false, file_created_dttm = null -
* geom(file_created_yn) 전부 false 리셋
*/ */
@Transactional @Transactional
public void resetForRegenerate(Long dataUid) { public void resetForRegenerate(Long dataUid) {
@@ -39,17 +36,13 @@ public class InferenceResultShpCoreService {
repo.resetGeomCreatedByDataUid(dataUid); repo.resetGeomCreatedByDataUid(dataUid);
} }
/** /** 생성 대상 geom 엔티티 로드 (file_created_yn=false/null + geom not null) */
* 생성 대상 geom 엔티티 로드 (file_created_yn=false/null + geom not null)
*/
@Transactional(readOnly = true) @Transactional(readOnly = true)
public List<MapSheetAnalDataInferenceGeomEntity> loadGeomEntities(Long dataUid, int limit) { public List<MapSheetAnalDataInferenceGeomEntity> loadGeomEntities(Long dataUid, int limit) {
return repo.findGeomEntitiesByDataUid(dataUid, limit); return repo.findGeomEntitiesByDataUid(dataUid, limit);
} }
/** /** 성공 마킹: - 성공 geo_uid만 geom.file_created_yn=true - inference.file_created_yn=true */
* 성공 마킹: - 성공 geo_uid만 geom.file_created_yn=true - inference.file_created_yn=true
*/
@Transactional @Transactional
public void markSuccess(Long dataUid, List<Long> geoUids) { public void markSuccess(Long dataUid, List<Long> geoUids) {
repo.markGeomCreatedByGeoUids(geoUids); repo.markGeomCreatedByGeoUids(geoUids);

View File

@@ -17,14 +17,13 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
private final JPAQueryFactory queryFactory; private final JPAQueryFactory queryFactory;
@PersistenceContext @PersistenceContext private final EntityManager em;
private final EntityManager em;
private final QMapSheetAnalDataInferenceEntity i = private final QMapSheetAnalDataInferenceEntity i =
QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity; QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity;
private final QMapSheetAnalDataInferenceGeomEntity g = private final QMapSheetAnalDataInferenceGeomEntity g =
QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity; QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
// =============================== // ===============================
// Upsert (Native only) // Upsert (Native only)
@@ -33,7 +32,8 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
@Override @Override
public int upsertGroupsFromInferenceResults() { public int upsertGroupsFromInferenceResults() {
String sql = """ String sql =
"""
INSERT INTO tb_map_sheet_anal_data_inference ( INSERT INTO tb_map_sheet_anal_data_inference (
stage, stage,
compare_yyyy, compare_yyyy,
@@ -68,7 +68,8 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
public int upsertGeomsFromInferenceResults() { public int upsertGeomsFromInferenceResults() {
// class_after_prob 컬럼 매핑 오타 주의(여기 제대로 넣음) // class_after_prob 컬럼 매핑 오타 주의(여기 제대로 넣음)
String sql = """ String sql =
"""
INSERT INTO tb_map_sheet_anal_data_inference_geom ( INSERT INTO tb_map_sheet_anal_data_inference_geom (
uuid, stage, cd_prob, compare_yyyy, target_yyyy, map_sheet_num, uuid, stage, cd_prob, compare_yyyy, target_yyyy, map_sheet_num,
class_before_cd, class_before_prob, class_after_cd, class_after_prob, class_before_cd, class_before_prob, class_after_cd, class_after_prob,
@@ -137,12 +138,12 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
@Override @Override
public List<Long> findPendingDataUids(int limit) { public List<Long> findPendingDataUids(int limit) {
return queryFactory return queryFactory
.select(i.id) // data_uid .select(i.id) // data_uid
.from(i) .from(i)
.where(i.fileCreatedYn.isFalse().or(i.fileCreatedYn.isNull())) .where(i.fileCreatedYn.isFalse().or(i.fileCreatedYn.isNull()))
.orderBy(i.id.asc()) .orderBy(i.id.asc())
.limit(limit) .limit(limit)
.fetch(); .fetch();
} }
// =============================== // ===============================
@@ -154,13 +155,13 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime now = ZonedDateTime.now();
return (int) return (int)
queryFactory queryFactory
.update(i) .update(i)
.set(i.fileCreatedYn, false) .set(i.fileCreatedYn, false)
.set(i.fileCreatedDttm, (ZonedDateTime) null) .set(i.fileCreatedDttm, (ZonedDateTime) null)
.set(i.updatedDttm, now) .set(i.updatedDttm, now)
.where(i.id.eq(dataUid)) .where(i.id.eq(dataUid))
.execute(); .execute();
} }
@Override @Override
@@ -168,13 +169,13 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime now = ZonedDateTime.now();
return (int) return (int)
queryFactory queryFactory
.update(i) .update(i)
.set(i.fileCreatedYn, true) .set(i.fileCreatedYn, true)
.set(i.fileCreatedDttm, now) .set(i.fileCreatedDttm, now)
.set(i.updatedDttm, now) .set(i.updatedDttm, now)
.where(i.id.eq(dataUid)) .where(i.id.eq(dataUid))
.execute(); .execute();
} }
@Override @Override
@@ -182,13 +183,13 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime now = ZonedDateTime.now();
return (int) return (int)
queryFactory queryFactory
.update(g) .update(g)
.set(g.fileCreatedYn, false) .set(g.fileCreatedYn, false)
.set(g.fileCreatedDttm, (ZonedDateTime) null) .set(g.fileCreatedDttm, (ZonedDateTime) null)
.set(g.updatedDttm, now) // ✅ 엔티티/Q가 ZonedDateTime이면 정상 .set(g.updatedDttm, now) // ✅ 엔티티/Q가 ZonedDateTime이면 정상
.where(g.dataUid.eq(dataUid)) .where(g.dataUid.eq(dataUid))
.execute(); .execute();
} }
@Override @Override
@@ -200,13 +201,13 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime now = ZonedDateTime.now();
return (int) return (int)
queryFactory queryFactory
.update(g) .update(g)
.set(g.fileCreatedYn, true) .set(g.fileCreatedYn, true)
.set(g.fileCreatedDttm, now) .set(g.fileCreatedDttm, now)
.set(g.updatedDttm, now) .set(g.updatedDttm, now)
.where(g.geoUid.in(geoUids)) .where(g.geoUid.in(geoUids))
.execute(); .execute();
} }
// =============================== // ===============================
@@ -214,15 +215,16 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
// =============================== // ===============================
@Override @Override
public List<MapSheetAnalDataInferenceGeomEntity> findGeomEntitiesByDataUid(Long dataUid, int limit) { public List<MapSheetAnalDataInferenceGeomEntity> findGeomEntitiesByDataUid(
Long dataUid, int limit) {
return queryFactory return queryFactory
.selectFrom(g) .selectFrom(g)
.where( .where(
g.dataUid.eq(dataUid), g.dataUid.eq(dataUid),
g.geom.isNotNull(), g.geom.isNotNull(),
g.fileCreatedYn.isFalse().or(g.fileCreatedYn.isNull())) g.fileCreatedYn.isFalse().or(g.fileCreatedYn.isNull()))
.orderBy(g.geoUid.asc()) .orderBy(g.geoUid.asc())
.limit(limit) .limit(limit)
.fetch(); .fetch();
} }
} }