Compare commits

...

1 커밋

작성자 SHA1 메시지 날짜
hyojin-kim4
20b8520a04 🔖 Batch Release Version : 1.1.0 (#5)
 S&P 수집 배치 데이터 검증값 추가 (정규화 이전)
* AIS
* Movements
* Events
* Risk&Compliance
* PSC
* Ships
* Facilities
---------

Co-authored-by: Kim JiMyeung <jmkim@gcsc8932.onmicrosoft.com>
Co-authored-by: HeungTak Lee <htlee@gcsc.co.kr>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 19:13:11 +09:00
125개의 변경된 파일1986개의 추가작업 그리고 3361개의 파일을 삭제

파일 보기

@ -13,7 +13,7 @@
</parent>
<groupId>com.snp</groupId>
<artifactId>snp-batch</artifactId>
<artifactId>snp-batch-validation</artifactId>
<version>1.0.0</version>
<name>SNP Batch</name>
<description>Spring Batch project for JSON to PostgreSQL with Web GUI</description>

파일 보기

@ -43,4 +43,22 @@ public abstract class BaseEntity {
* 컬럼: updated_by (VARCHAR(100))
*/
private String updatedBy;
/**
* 배치 실행 ID
* 컬럼: job_execution_id (int8)
*/
private Long jobExecutionId;
/**
* 배치 공통 필드 설정을 위한 편의 메서드
*/
@SuppressWarnings("unchecked")
public <T extends BaseEntity> T setBatchInfo(Long jobExecutionId, String createdBy) {
this.jobExecutionId = jobExecutionId;
this.createdBy = createdBy;
// 필요시 생성일시 강제 설정 (JPA Auditing을 경우)
if (this.createdAt == null) this.createdAt = LocalDateTime.now();
return (T) this;
}
}

파일 보기

@ -170,6 +170,125 @@ public abstract class BaseApiReader<T> implements ItemReader<T> {
}
}
protected <T, R> List<R> executeWrapperApiCall(
String baseUrl,
String path,
Class<T> responseWrapperClass, // Stat5CodeApiResponse.class 등을 받음
Function<T, List<R>> listExtractor, // 결과 객체에서 리스트를 꺼내는 로직
BatchApiLogService logService) {
String fullUri = UriComponentsBuilder.fromHttpUrl(baseUrl)
.path(path)
.build()
.toUriString();
long startTime = System.currentTimeMillis();
int statusCode = 200;
String errorMessage = null;
Long responseSize = 0L;
try {
log.info("[{}] API 요청 시작: {}", getReaderName(), fullUri);
// 1. List<R> 아닌 Wrapper 객체(T) 받아옵니다.
T response = webClient.get()
.uri(uriBuilder -> uriBuilder.path(path).build())
.retrieve()
.bodyToMono(responseWrapperClass)
.block();
// 2. 추출 함수(listExtractor) 사용하여 내부 리스트를 꺼냅니다.
List<R> result = (response != null) ? listExtractor.apply(response) : Collections.emptyList();
responseSize = (long) result.size();
return result;
} catch (WebClientResponseException e) {
statusCode = e.getStatusCode().value();
errorMessage = String.format("API Error: %s", e.getResponseBodyAsString());
throw e;
} catch (Exception e) {
statusCode = 500;
errorMessage = String.format("System Error: %s", e.getMessage());
throw e;
} finally {
long duration = System.currentTimeMillis() - startTime;
logService.saveLog(BatchApiLog.builder()
.apiRequestLocation(getReaderName())
.requestUri(fullUri)
.httpMethod("GET")
.statusCode(statusCode)
.responseTimeMs(duration)
.responseCount(responseSize)
.errorMessage(errorMessage)
.createdAt(LocalDateTime.now())
.jobExecutionId(this.jobExecutionId)
.stepExecutionId(this.stepExecutionId)
.build());
}
}
protected <R> List<R> executeListApiCall(
String baseUrl,
String path,
ParameterizedTypeReference<List<R>> typeReference,
BatchApiLogService logService) {
String fullUri = UriComponentsBuilder.fromHttpUrl(baseUrl)
.path(path)
.build()
.toUriString();
long startTime = System.currentTimeMillis();
int statusCode = 200;
String errorMessage = null;
Long responseSize = 0L;
try {
log.info("[{}] API 요청 시작: {}", getReaderName(), fullUri);
List<R> result = webClient.get()
.uri(uriBuilder -> {
uriBuilder.path(path);
return uriBuilder.build();
})
.retrieve()
.bodyToMono(typeReference)
.block();
responseSize = (result != null) ? (long) result.size() : 0L;
return result;
} catch (WebClientResponseException e) {
// API 서버에서 응답은 왔으나 에러인 경우 (4xx, 5xx)
statusCode = e.getStatusCode().value();
errorMessage = String.format("API Error: %s", e.getResponseBodyAsString());
throw e;
} catch (Exception e) {
// 네트워크 오류, 타임아웃 기타 예외
statusCode = 500;
errorMessage = String.format("System Error: %s", e.getMessage());
throw e;
} finally {
// 성공/실패 여부와 관계없이 무조건 로그 저장
long duration = System.currentTimeMillis() - startTime;
logService.saveLog(BatchApiLog.builder()
.apiRequestLocation(getReaderName())
.requestUri(fullUri)
.httpMethod("GET")
.statusCode(statusCode)
.responseTimeMs(duration)
.responseCount(responseSize)
.errorMessage(errorMessage)
.createdAt(LocalDateTime.now())
.jobExecutionId(this.jobExecutionId) // 추가
.stepExecutionId(this.stepExecutionId) // 추가
.build());
}
}
/**
* API 호출 로그 적재 통합 메서드
* Response Json 구조 : { "data": [...] }

파일 보기

@ -7,7 +7,7 @@ import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
@Entity
@Table(name = "batch_api_log", schema = "snp_data")
@Table(name = "batch_api_log", schema = "t_snp_data")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor

파일 보기

@ -7,9 +7,12 @@ import com.snp.batch.jobs.common.batch.processor.FlagCodeDataProcessor;
import com.snp.batch.jobs.common.batch.reader.FlagCodeDataReader;
import com.snp.batch.jobs.common.batch.repository.FlagCodeRepository;
import com.snp.batch.jobs.common.batch.writer.FlagCodeDataWriter;
import com.snp.batch.jobs.facility.batch.reader.PortDataReader;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
@ -25,8 +28,14 @@ import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class FlagCodeImportJobConfig extends BaseJobConfig<FlagCodeDto, FlagCodeEntity> {
private final FlagCodeDataProcessor flagCodeDataProcessor;
private final FlagCodeDataReader flagCodeDataReader;
private final FlagCodeRepository flagCodeRepository;
private final WebClient maritimeApiWebClient;
private final BatchApiLogService batchApiLogService;
@Value("${app.batch.ship-api.url}")
private String maritimeApiUrl;
@Value("${app.batch.chunk-size:1000}")
private int chunkSize;
@ -39,10 +48,16 @@ public class FlagCodeImportJobConfig extends BaseJobConfig<FlagCodeDto, FlagCode
JobRepository jobRepository,
PlatformTransactionManager transactionManager,
FlagCodeRepository flagCodeRepository,
@Qualifier("maritimeApiWebClient") WebClient maritimeApiWebClient) {
FlagCodeDataProcessor flagCodeDataProcessor,
@Qualifier("maritimeApiWebClient") WebClient maritimeApiWebClient,
FlagCodeDataReader flagCodeDataReader,
BatchApiLogService batchApiLogService) {
super(jobRepository, transactionManager);
this.flagCodeRepository = flagCodeRepository;
this.maritimeApiWebClient = maritimeApiWebClient;
this.flagCodeDataProcessor = flagCodeDataProcessor;
this.flagCodeDataReader = flagCodeDataReader;
this.batchApiLogService = batchApiLogService;
}
@Override
@ -57,14 +72,29 @@ public class FlagCodeImportJobConfig extends BaseJobConfig<FlagCodeDto, FlagCode
@Override
protected ItemReader<FlagCodeDto> createReader() {
return new FlagCodeDataReader(maritimeApiWebClient);
return flagCodeDataReader;
}
@Bean
@StepScope
public FlagCodeDataReader flagCodeDataReader(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId, // SpEL로 ID 추출
@Value("#{stepExecution.id}") Long stepExecutionId
) {
FlagCodeDataReader reader = new FlagCodeDataReader(maritimeApiWebClient, batchApiLogService, maritimeApiUrl);
reader.setExecutionIds(jobExecutionId, stepExecutionId); // ID 세팅
return reader;
}
@Override
protected ItemProcessor<FlagCodeDto, FlagCodeEntity> createProcessor() {
return new FlagCodeDataProcessor(flagCodeRepository);
return flagCodeDataProcessor;
}
@Bean
@StepScope
public FlagCodeDataProcessor flagCodeDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new FlagCodeDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<FlagCodeEntity> createWriter() {
return new FlagCodeDataWriter(flagCodeRepository);

파일 보기

@ -7,14 +7,17 @@ import com.snp.batch.jobs.common.batch.processor.Stat5CodeDataProcessor;
import com.snp.batch.jobs.common.batch.reader.Stat5CodeDataReader;
import com.snp.batch.jobs.common.batch.repository.Stat5CodeRepository;
import com.snp.batch.jobs.common.batch.writer.Stat5CodeDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@ -24,16 +27,27 @@ import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class Stat5CodeImportJobConfig extends BaseJobConfig<Stat5CodeDto, Stat5CodeEntity> {
private final Stat5CodeDataProcessor stat5CodeDataProcessor;
private final Stat5CodeDataReader stat5CodeDataReader;
private final Stat5CodeRepository stat5CodeRepository;
private final BatchApiLogService batchApiLogService;
private final WebClient maritimeAisApiWebClient;
@Value("${app.batch.ais-api.url}")
private String maritimeAisApiUrl;
public Stat5CodeImportJobConfig(
JobRepository jobRepository,
PlatformTransactionManager transactionManager,
Stat5CodeRepository stat5CodeRepository,
@Qualifier("maritimeAisApiWebClient") WebClient maritimeAisApiWebClient) {
@Qualifier("maritimeAisApiWebClient") WebClient maritimeAisApiWebClient,
Stat5CodeDataProcessor stat5CodeDataProcessor,
Stat5CodeDataReader stat5CodeDataReader,
BatchApiLogService batchApiLogService) {
super(jobRepository, transactionManager);
this.stat5CodeRepository = stat5CodeRepository;
this.maritimeAisApiWebClient = maritimeAisApiWebClient;
this.stat5CodeDataProcessor = stat5CodeDataProcessor;
this.stat5CodeDataReader = stat5CodeDataReader;
this.batchApiLogService = batchApiLogService;
}
@Override
@ -45,11 +59,27 @@ public class Stat5CodeImportJobConfig extends BaseJobConfig<Stat5CodeDto, Stat5C
}
@Override
protected ItemReader<Stat5CodeDto> createReader() { return new Stat5CodeDataReader(maritimeAisApiWebClient); }
protected ItemReader<Stat5CodeDto> createReader() { return stat5CodeDataReader; }
@Bean
@StepScope
public Stat5CodeDataReader stat5CodeDataReader(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId, // SpEL로 ID 추출
@Value("#{stepExecution.id}") Long stepExecutionId
) {
Stat5CodeDataReader reader = new Stat5CodeDataReader(maritimeAisApiWebClient, batchApiLogService, maritimeAisApiUrl);
reader.setExecutionIds(jobExecutionId, stepExecutionId); // ID 세팅
return reader;
}
@Override
protected ItemProcessor<Stat5CodeDto, Stat5CodeEntity> createProcessor() { return new Stat5CodeDataProcessor(stat5CodeRepository); }
protected ItemProcessor<Stat5CodeDto, Stat5CodeEntity> createProcessor() { return stat5CodeDataProcessor; }
@Bean
@StepScope
public Stat5CodeDataProcessor stat5CodeDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new Stat5CodeDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<Stat5CodeEntity> createWriter() { return new Stat5CodeDataWriter(stat5CodeRepository); }

파일 보기

@ -3,16 +3,16 @@ package com.snp.batch.jobs.common.batch.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.common.batch.dto.FlagCodeDto;
import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
import com.snp.batch.jobs.common.batch.repository.FlagCodeRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@Slf4j
public class FlagCodeDataProcessor extends BaseProcessor<FlagCodeDto, FlagCodeEntity> {
private final FlagCodeRepository commonCodeRepository;
private final Long jobExecutionId;
public FlagCodeDataProcessor(FlagCodeRepository commonCodeRepository) {
this.commonCodeRepository = commonCodeRepository;
public FlagCodeDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
@ -24,6 +24,8 @@ public class FlagCodeDataProcessor extends BaseProcessor<FlagCodeDto, FlagCodeEn
.decode(dto.getDecode())
.iso2(dto.getIso2())
.iso3(dto.getIso3())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
log.debug("국가코드 데이터 처리 완료: FlagCode={}", dto.getCode());

파일 보기

@ -3,16 +3,16 @@ package com.snp.batch.jobs.common.batch.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.common.batch.dto.Stat5CodeDto;
import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
import com.snp.batch.jobs.common.batch.repository.Stat5CodeRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@Slf4j
public class Stat5CodeDataProcessor extends BaseProcessor<Stat5CodeDto, Stat5CodeEntity> {
private final Stat5CodeRepository stat5CodeRepository;
private final Long jobExecutionId;
public Stat5CodeDataProcessor(Stat5CodeRepository stat5CodeRepository) {
this.stat5CodeRepository = stat5CodeRepository;
public Stat5CodeDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
@ -30,6 +30,8 @@ public class Stat5CodeDataProcessor extends BaseProcessor<Stat5CodeDto, Stat5Cod
.Level5Decode(dto.getLevel5Decode())
.Description(dto.getDescription())
.Release(Integer.toString(dto.getRelease()))
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
log.debug("Stat5Code 데이터 처리 완료: Stat5Code={}", dto.getLevel5());

파일 보기

@ -3,17 +3,22 @@ package com.snp.batch.jobs.common.batch.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
import com.snp.batch.jobs.common.batch.dto.FlagCodeApiResponse;
import com.snp.batch.jobs.common.batch.dto.FlagCodeDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
public class FlagCodeDataReader extends BaseApiReader<FlagCodeDto> {
public FlagCodeDataReader(WebClient webClient) {
private final BatchApiLogService batchApiLogService;
String maritimeApiUrl;
public FlagCodeDataReader(WebClient webClient, BatchApiLogService batchApiLogService, String maritimeApiUrl) {
super(webClient); // BaseApiReader에 WebClient 전달
this.batchApiLogService = batchApiLogService;
this.maritimeApiUrl = maritimeApiUrl;
}
// ========================================
@ -24,28 +29,25 @@ public class FlagCodeDataReader extends BaseApiReader<FlagCodeDto> {
protected String getReaderName() {
return "FlagCodeDataReader";
}
@Override
protected String getApiPath() {
return "/MaritimeWCF/APSShipService.svc/RESTFul/GetAssociatedFlagISOByName";
}
@Override
protected List<FlagCodeDto> fetchDataFromApi() {
try {
log.info("GetAssociatedFlagISOByName API 호출 시작");
FlagCodeApiResponse response = webClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/MaritimeWCF/APSShipService.svc/RESTFul/GetAssociatedFlagISOByName")
.build())
.retrieve()
.bodyToMono(FlagCodeApiResponse.class)
.block();
if (response != null && response.getAssociatedFlagISODetails() != null) {
log.info("API 응답 성공: 총 {} 건의 국가코드 데이터 수신", response.getAssociatedCount());
return response.getAssociatedFlagISODetails();
} else {
log.warn("API 응답이 null이거나 국가코드 데이터가 없습니다");
return new ArrayList<>();
}
// 공통 함수 호출
List<FlagCodeDto> result = executeWrapperApiCall(
maritimeApiUrl, // 베이스 URL (필드 또는 설정값)
getApiPath(), // API 경로
FlagCodeApiResponse.class, // 응답을 받을 래퍼 클래스
FlagCodeApiResponse::getAssociatedFlagISODetails, // 리스트 추출 함수 (메서드 참조)
batchApiLogService // 로그 서비스
);
// 결과가 null일 경우 리스트 반환 (안전장치)
return result != null ? result : Collections.emptyList();
} catch (Exception e) {
log.error("GetAssociatedFlagISOByName API 호출 실패", e);

파일 보기

@ -3,43 +3,46 @@ package com.snp.batch.jobs.common.batch.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
import com.snp.batch.jobs.common.batch.dto.Stat5CodeApiResponse;
import com.snp.batch.jobs.common.batch.dto.Stat5CodeDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
public class Stat5CodeDataReader extends BaseApiReader<Stat5CodeDto> {
public Stat5CodeDataReader(WebClient webClient) {
private final BatchApiLogService batchApiLogService;
String maritimeAisApiUrl;
public Stat5CodeDataReader(WebClient webClient, BatchApiLogService batchApiLogService, String maritimeAisApiUrl) {
super(webClient); // BaseApiReader에 WebClient 전달
this.batchApiLogService = batchApiLogService;
this.maritimeAisApiUrl = maritimeAisApiUrl;
}
@Override
protected String getReaderName() {
return "Stat5CodeDataReader";
}
@Override
protected String getApiPath() {
return "/AisSvc.svc/AIS/GetStatcodes";
}
@Override
protected List<Stat5CodeDto> fetchDataFromApi() {
try {
log.info("GetStatcodes API 호출 시작");
Stat5CodeApiResponse response = webClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/AisSvc.svc/AIS/GetStatcodes")
.build())
.retrieve()
.bodyToMono(Stat5CodeApiResponse.class)
.block();
if (response != null && response.getStatcodeArr() != null) {
log.info("API 응답 성공: 총 {} 건의 Stat5Code 데이터 수신", response.getStatcodeArr().size());
return response.getStatcodeArr();
} else {
log.warn("API 응답이 null이거나 Stat5Code 데이터가 없습니다");
return new ArrayList<>();
}
// 공통 함수 호출
List<Stat5CodeDto> result = executeWrapperApiCall(
maritimeAisApiUrl, // 베이스 URL (필드 또는 설정값)
getApiPath(), // API 경로
Stat5CodeApiResponse.class, // 응답을 받을 래퍼 클래스
Stat5CodeApiResponse::getStatcodeArr, // 리스트 추출 함수 (메서드 참조)
batchApiLogService // 로그 서비스
);
// 결과가 null일 경우 리스트 반환 (안전장치)
return result != null ? result : Collections.emptyList();
} catch (Exception e) {
log.error("GetAssociatedFlagISOByName API 호출 실패", e);
log.error("에러 메시지: {}", e.getMessage());

파일 보기

@ -8,6 +8,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.List;
@Slf4j
@ -25,7 +26,7 @@ public class FlagCodeRepositoryImpl extends BaseJdbcRepository<FlagCodeEntity, S
@Override
protected String getTableName() {
return "snp_data.flagcode";
return "t_snp_data.flagcode";
}
@ -37,17 +38,11 @@ public class FlagCodeRepositoryImpl extends BaseJdbcRepository<FlagCodeEntity, S
@Override
protected String getUpdateSql() {
return """
INSERT INTO snp_data.flagcode (
datasetversion, code, decode, iso2, iso3
) VALUES (?, ?, ?, ?, ?)
ON CONFLICT (code)
DO UPDATE SET
datasetversion = EXCLUDED.datasetversion,
decode = EXCLUDED.decode,
iso2 = EXCLUDED.iso2,
iso3 = EXCLUDED.iso3,
batch_flag = 'N'
""";
INSERT INTO %s(
datasetversion, code, decode, iso2, iso3,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -63,6 +58,8 @@ public class FlagCodeRepositoryImpl extends BaseJdbcRepository<FlagCodeEntity, S
ps.setString(idx++, entity.getDecode());
ps.setString(idx++, entity.getIso2());
ps.setString(idx++, entity.getIso3());
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override

파일 보기

@ -8,6 +8,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.List;
@Slf4j
@ -24,7 +25,7 @@ public class Stat5CodeRepositoryImpl extends BaseJdbcRepository<Stat5CodeEntity,
@Override
protected String getTableName() {
return "snp_data.stat5code";
return "t_snp_data.stat5code";
}
@Override
@ -45,25 +46,11 @@ public class Stat5CodeRepositoryImpl extends BaseJdbcRepository<Stat5CodeEntity,
@Override
protected String getUpdateSql() {
return """
INSERT INTO snp_data.stat5code (
level1, level1decode, level2, level2decode, level3, level3decode, level4, level4decode, level5, level5decode, description, release
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (level1, level2, level3, level4, level5)
DO UPDATE SET
level1 = EXCLUDED.level1,
level1decode = EXCLUDED.level1decode,
level2 = EXCLUDED.level2,
level2decode = EXCLUDED.level2decode,
level3 = EXCLUDED.level3,
level3decode = EXCLUDED.level3decode,
level4 = EXCLUDED.level4,
level4decode = EXCLUDED.level4decode,
level5 = EXCLUDED.level5,
level5decode = EXCLUDED.level5decode,
description = EXCLUDED.description,
release = EXCLUDED.release,
batch_flag = 'N'
""";
INSERT INTO %s(
level1, level1decode, level2, level2decode, level3, level3decode, level4, level4decode, level5, level5decode, description, release,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -86,6 +73,8 @@ public class Stat5CodeRepositoryImpl extends BaseJdbcRepository<Stat5CodeEntity,
ps.setString(idx++, entity.getLevel5Decode());
ps.setString(idx++, entity.getDescription());
ps.setString(idx++, entity.getRelease());
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override

파일 보기

@ -2,12 +2,9 @@ package com.snp.batch.jobs.compliance.batch.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.compliance.batch.dto.CompanyComplianceDto;
import com.snp.batch.jobs.compliance.batch.dto.ComplianceDto;
import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
import com.snp.batch.jobs.compliance.batch.processor.CompanyComplianceDataProcessor;
import com.snp.batch.jobs.compliance.batch.reader.CompanyComplianceDataRangeReader;
import com.snp.batch.jobs.compliance.batch.reader.ComplianceDataRangeReader;
import com.snp.batch.jobs.compliance.batch.writer.CompanyComplianceDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
@ -52,7 +49,7 @@ public class CompanyComplianceImportRangeJobConfig extends BaseMultiStepJobConfi
private String maritimeServiceApiUrl;
protected String getApiKey() {return "COMPANY_COMPLIANCE_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
@Override
protected int getChunkSize() {
@ -91,7 +88,7 @@ public class CompanyComplianceImportRangeJobConfig extends BaseMultiStepJobConfi
protected Job createJobFlow(JobBuilder jobBuilder) {
return jobBuilder
.start(companyComplianceImportRangeStep()) // 1단계 실행
.next(companyComplianceHistoryValueChangeManageStep()) // 2단계 실행 (2단계 실패 실행 )
// .next(companyComplianceHistoryValueChangeManageStep()) // 2단계 실행 (2단계 실패 실행 )
.next(companyComplianceLastExecutionUpdateStep()) // 3단계: 모두 완료 , BATCH_LAST_EXECUTION 마지막 성공일자 업데이트
.build();
}
@ -115,7 +112,12 @@ public class CompanyComplianceImportRangeJobConfig extends BaseMultiStepJobConfi
protected ItemProcessor<CompanyComplianceDto, CompanyComplianceEntity> createProcessor() {
return companyComplianceDataProcessor;
}
@Bean
@StepScope
public CompanyComplianceDataProcessor companyComplianceDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new CompanyComplianceDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<CompanyComplianceEntity> createWriter() {
return companyComplianceDataWriter;

파일 보기

@ -28,7 +28,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.reactive.function.client.WebClient;
import java.time.*;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Map;
@ -47,7 +48,7 @@ public class ComplianceImportRangeJobConfig extends BaseMultiStepJobConfig<Compl
private String maritimeServiceApiUrl;
protected String getApiKey() {return "COMPLIANCE_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
@Override
protected int getChunkSize() {
@ -87,7 +88,7 @@ public class ComplianceImportRangeJobConfig extends BaseMultiStepJobConfig<Compl
protected Job createJobFlow(JobBuilder jobBuilder) {
return jobBuilder
.start(complianceImportRangeStep()) // 1단계 실행
.next(complianceHistoryValueChangeManageStep()) // 2단계 실행 (2단계 실패 실행 )
// .next(complianceHistoryValueChangeManageStep()) // 2단계 실행 (2단계 실패 실행 )
.next(complianceLastExecutionUpdateStep()) // 3단계: 모두 완료 , BATCH_LAST_EXECUTION 마지막 성공일자 업데이트
.build();
}
@ -112,6 +113,13 @@ public class ComplianceImportRangeJobConfig extends BaseMultiStepJobConfig<Compl
return complianceDataProcessor;
}
@Bean
@StepScope
public ComplianceDataProcessor complianceDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new ComplianceDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<ComplianceEntity> createWriter() {
return complianceDataWriter;

파일 보기

@ -4,12 +4,16 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.compliance.batch.dto.CompanyComplianceDto;
import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class CompanyComplianceDataProcessor extends BaseProcessor<CompanyComplianceDto, CompanyComplianceEntity> {
private final Long jobExecutionId;
public CompanyComplianceDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
protected CompanyComplianceEntity processItem(CompanyComplianceDto dto) throws Exception {
@ -30,6 +34,8 @@ public class CompanyComplianceDataProcessor extends BaseProcessor<CompanyComplia
.companyOnSwissSanctionList(dto.getCompanyOnSwissSanctionList())
.companyOnUAESanctionList(dto.getCompanyOnUAESanctionList())
.companyOnUNSanctionList(dto.getCompanyOnUNSanctionList())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;
}

파일 보기

@ -4,11 +4,16 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.compliance.batch.dto.ComplianceDto;
import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ComplianceDataProcessor extends BaseProcessor<ComplianceDto, ComplianceEntity> {
private final Long jobExecutionId;
public ComplianceDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
protected ComplianceEntity processItem(ComplianceDto dto) throws Exception {
@ -50,6 +55,8 @@ public class ComplianceDataProcessor extends BaseProcessor<ComplianceDto, Compli
.shipSTSPartnerNonComplianceLast12m(dto.getShipSTSPartnerNonComplianceLast12m())
.shipSwissSanctionList(dto.getShipSwissSanctionList())
.shipUNSanctionList(dto.getShipUNSanctionList())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,5 +6,5 @@ import java.util.List;
public interface CompanyComplianceRepository {
void saveCompanyComplianceAll(List<CompanyComplianceEntity> items);
void saveCompanyComplianceHistoryAll(List<CompanyComplianceEntity> items);
// void saveCompanyComplianceHistoryAll(List<CompanyComplianceEntity> items);
}

파일 보기

@ -20,7 +20,7 @@ public class CompanyComplianceRepositoryImpl extends BaseJdbcRepository<CompanyC
@Override
protected String getTableName() {
return null;
return "t_snp_data.tb_company_compliance_info";
}
@Override
@ -40,35 +40,18 @@ public class CompanyComplianceRepositoryImpl extends BaseJdbcRepository<CompanyC
@Override
protected String getUpdateSql() {
return null;
}
protected String getUpdateSql(String targetTable, String targetIndex) {
return """
INSERT INTO new_snp.%s(
INSERT INTO %s(
owcode, lastupdated,
companyoverallcompliancestatus, companyonaustraliansanctionlist, companyonbessanctionlist, companyoncanadiansanctionlist, companyinofacsanctionedcountry,
companyinfatfjurisdiction, companyoneusanctionlist, companyonofacsanctionlist, companyonofacnonsdnsanctionlist, companyonofacssilist,
companyonswisssanctionlist, companyonuaesanctionlist, companyonunsanctionlist, parentcompanycompliancerisk
companyonswisssanctionlist, companyonuaesanctionlist, companyonunsanctionlist, parentcompanycompliancerisk,
job_execution_id, created_by
)VALUES(
?, ?::timestamp, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)ON CONFLICT (%s)
DO UPDATE SET
companyoverallcompliancestatus = EXCLUDED.companyoverallcompliancestatus,
companyonaustraliansanctionlist = EXCLUDED.companyonaustraliansanctionlist,
companyonbessanctionlist = EXCLUDED.companyonbessanctionlist,
companyoncanadiansanctionlist = EXCLUDED.companyoncanadiansanctionlist,
companyinofacsanctionedcountry = EXCLUDED.companyinofacsanctionedcountry,
companyinfatfjurisdiction = EXCLUDED.companyinfatfjurisdiction,
companyoneusanctionlist = EXCLUDED.companyoneusanctionlist,
companyonofacsanctionlist = EXCLUDED.companyonofacsanctionlist,
companyonofacnonsdnsanctionlist = EXCLUDED.companyonofacnonsdnsanctionlist,
companyonofacssilist = EXCLUDED.companyonofacssilist,
companyonswisssanctionlist = EXCLUDED.companyonswisssanctionlist,
companyonuaesanctionlist = EXCLUDED.companyonuaesanctionlist,
companyonunsanctionlist = EXCLUDED.companyonunsanctionlist,
parentcompanycompliancerisk = EXCLUDED.parentcompanycompliancerisk
""".formatted(targetTable, targetIndex);
?, ?::timestamp, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?
);
""".formatted(getTableName());
}
@Override
@ -94,6 +77,8 @@ public class CompanyComplianceRepositoryImpl extends BaseJdbcRepository<CompanyC
ps.setObject(idx++, entity.getCompanyOnUAESanctionList(), Types.INTEGER);
ps.setObject(idx++, entity.getCompanyOnUNSanctionList(), Types.INTEGER);
ps.setObject(idx++, entity.getParentCompanyNonCompliance(), Types.INTEGER);
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override
@ -106,7 +91,7 @@ public class CompanyComplianceRepositoryImpl extends BaseJdbcRepository<CompanyC
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("tb_company_compliance_info", "owcode"), items, items.size(),
jdbcTemplate.batchUpdate(getUpdateSql(), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);
@ -118,20 +103,4 @@ public class CompanyComplianceRepositoryImpl extends BaseJdbcRepository<CompanyC
log.info("{} 전체 저장 완료: 수정={} 건", getEntityName(), items.size());
}
@Override
public void saveCompanyComplianceHistoryAll(List<CompanyComplianceEntity> items) {
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("tb_company_compliance_hstry", "owcode, lastupdated"), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);
} catch (Exception e) {
log.error("배치 수정 파라미터 설정 실패", e);
throw new RuntimeException(e);
}
});
log.info("{} 전체 저장 완료: 수정={} 건", getEntityName(), items.size());
}
}

파일 보기

@ -6,5 +6,5 @@ import java.util.List;
public interface ComplianceRepository {
void saveComplianceAll(List<ComplianceEntity> items);
void saveComplianceHistoryAll(List<ComplianceEntity> items);
// void saveComplianceHistoryAll(List<ComplianceEntity> items);
}

파일 보기

@ -21,7 +21,7 @@ public class ComplianceRepositoryImpl extends BaseJdbcRepository<ComplianceEntit
@Override
protected String getTableName() {
return null;
return "t_snp_data.compliance";
}
@Override
@ -41,12 +41,8 @@ public class ComplianceRepositoryImpl extends BaseJdbcRepository<ComplianceEntit
@Override
protected String getUpdateSql() {
return null;
}
protected String getUpdateSql(String targetTable, String targetIndex) {
return """
INSERT INTO new_snp.%s (
INSERT INTO %s (
lrimoshipno, dateamended, legaloverall, shipbessanctionlist, shipdarkactivityindicator,
shipdetailsnolongermaintained, shipeusanctionlist, shipflagdisputed, shipflagsanctionedcountry,
shiphistoricalflagsanctionedcountry, shipofacnonsdnsanctionlist, shipofacsanctionlist,
@ -57,47 +53,14 @@ public class ComplianceRepositoryImpl extends BaseJdbcRepository<ComplianceEntit
shipownerswisssanctionlist, shipowneruaesanctionlist, shipownerunsanctionlist,
shipsanctionedcountryportcalllast12m, shipsanctionedcountryportcalllast3m, shipsanctionedcountryportcalllast6m,
shipsecuritylegaldisputeevent, shipstspartnernoncompliancelast12m, shipswisssanctionlist,
shipunsanctionlist
shipunsanctionlist,
job_execution_id, created_by
)
VALUES (
?, ?::timestamptz, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
ON CONFLICT (%s)
DO UPDATE SET
legaloverall = EXCLUDED.legaloverall,
shipbessanctionlist = EXCLUDED.shipbessanctionlist,
shipdarkactivityindicator = EXCLUDED.shipdarkactivityindicator,
shipdetailsnolongermaintained = EXCLUDED.shipdetailsnolongermaintained,
shipeusanctionlist = EXCLUDED.shipeusanctionlist,
shipflagdisputed = EXCLUDED.shipflagdisputed,
shipflagsanctionedcountry = EXCLUDED.shipflagsanctionedcountry,
shiphistoricalflagsanctionedcountry = EXCLUDED.shiphistoricalflagsanctionedcountry,
shipofacnonsdnsanctionlist = EXCLUDED.shipofacnonsdnsanctionlist,
shipofacsanctionlist = EXCLUDED.shipofacsanctionlist,
shipofacadvisorylist = EXCLUDED.shipofacadvisorylist,
shipownerofacssilist = EXCLUDED.shipownerofacssilist,
shipowneraustraliansanctionlist = EXCLUDED.shipowneraustraliansanctionlist,
shipownerbessanctionlist = EXCLUDED.shipownerbessanctionlist,
shipownercanadiansanctionlist = EXCLUDED.shipownercanadiansanctionlist,
shipownereusanctionlist = EXCLUDED.shipownereusanctionlist,
shipownerfatfjurisdiction = EXCLUDED.shipownerfatfjurisdiction,
shipownerhistoricalofacsanctionedcountry = EXCLUDED.shipownerhistoricalofacsanctionedcountry,
shipownerofacsanctionlist = EXCLUDED.shipownerofacsanctionlist,
shipownerofacsanctionedcountry = EXCLUDED.shipownerofacsanctionedcountry,
shipownerparentcompanynoncompliance = EXCLUDED.shipownerparentcompanynoncompliance,
shipownerparentfatfjurisdiction = EXCLUDED.shipownerparentfatfjurisdiction,
shipownerparentofacsanctionedcountry = EXCLUDED.shipownerparentofacsanctionedcountry,
shipownerswisssanctionlist = EXCLUDED.shipownerswisssanctionlist,
shipowneruaesanctionlist = EXCLUDED.shipowneruaesanctionlist,
shipownerunsanctionlist = EXCLUDED.shipownerunsanctionlist,
shipsanctionedcountryportcalllast12m = EXCLUDED.shipsanctionedcountryportcalllast12m,
shipsanctionedcountryportcalllast3m = EXCLUDED.shipsanctionedcountryportcalllast3m,
shipsanctionedcountryportcalllast6m = EXCLUDED.shipsanctionedcountryportcalllast6m,
shipsecuritylegaldisputeevent = EXCLUDED.shipsecuritylegaldisputeevent,
shipstspartnernoncompliancelast12m = EXCLUDED.shipstspartnernoncompliancelast12m,
shipswisssanctionlist = EXCLUDED.shipswisssanctionlist,
shipunsanctionlist = EXCLUDED.shipunsanctionlist
""".formatted(targetTable, targetIndex);
?, ?::timestamptz, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?
);
""".formatted(getTableName());
}
@Override
@ -143,6 +106,8 @@ public class ComplianceRepositoryImpl extends BaseJdbcRepository<ComplianceEntit
ps.setObject(idx++, entity.getShipSTSPartnerNonComplianceLast12m(), Types.INTEGER);
ps.setObject(idx++, entity.getShipSwissSanctionList(), Types.INTEGER);
ps.setObject(idx++, entity.getShipUNSanctionList(), Types.INTEGER);
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override
@ -155,24 +120,7 @@ public class ComplianceRepositoryImpl extends BaseJdbcRepository<ComplianceEntit
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("compliance", "lrimoshipno"), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);
} catch (Exception e) {
log.error("배치 수정 파라미터 설정 실패", e);
throw new RuntimeException(e);
}
});
log.info("{} 전체 저장 완료: 수정={} 건", getEntityName(), items.size());
}
@Override
public void saveComplianceHistoryAll(List<ComplianceEntity> items) {
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("compliance_history", "lrimoshipno, dateamended"), items, items.size(),
jdbcTemplate.batchUpdate(getUpdateSql(), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);

파일 보기

@ -20,6 +20,6 @@ public class CompanyComplianceDataWriter extends BaseWriter<CompanyComplianceEnt
@Override
protected void writeItems(List<CompanyComplianceEntity> items) throws Exception {
complianceRepository.saveCompanyComplianceAll(items);
complianceRepository.saveCompanyComplianceHistoryAll(items);
// complianceRepository.saveCompanyComplianceHistoryAll(items);
}
}

파일 보기

@ -19,6 +19,6 @@ public class ComplianceDataWriter extends BaseWriter<ComplianceEntity> {
@Override
protected void writeItems(List<ComplianceEntity> items) throws Exception {
complianceRepository.saveComplianceAll(items);
complianceRepository.saveComplianceHistoryAll(items);
// complianceRepository.saveComplianceHistoryAll(items);
}
}

파일 보기

@ -44,7 +44,7 @@ public class EventImportJobConfig extends BaseMultiStepJobConfig<EventDetailDto,
protected String getApiKey() {return "EVENT_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
@Override
protected int getChunkSize() {
@ -109,6 +109,14 @@ public class EventImportJobConfig extends BaseMultiStepJobConfig<EventDetailDto,
return eventDataProcessor;
}
@Bean
@StepScope
public EventDataProcessor eventDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId
){
return new EventDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<EventDetailEntity> createWriter() { return eventDataWriter; }

파일 보기

@ -1,12 +1,17 @@
package com.snp.batch.jobs.event.batch.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.event.batch.dto.CargoDto;
import com.snp.batch.jobs.event.batch.dto.EventDetailDto;
import com.snp.batch.jobs.event.batch.dto.HumanCasualtyDto;
import com.snp.batch.jobs.event.batch.dto.RelationshipDto;
import com.snp.batch.jobs.event.batch.entity.CargoEntity;
import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
import com.snp.batch.jobs.event.batch.entity.HumanCasualtyEntity;
import com.snp.batch.jobs.event.batch.entity.RelationshipEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.stream.Collectors;
@ -14,6 +19,12 @@ import java.util.stream.Collectors;
@Slf4j
@Component
public class EventDataProcessor extends BaseProcessor<EventDetailDto, EventDetailEntity> {
private static Long jobExecutionId;
public EventDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId
) {
this.jobExecutionId = jobExecutionId;
}
@Override
protected EventDetailEntity processItem(EventDetailDto dto) throws Exception {
log.debug("Event 데이터 처리 시작: Event ID = {}", dto.getEventID());
@ -61,12 +72,20 @@ public class EventDataProcessor extends BaseProcessor<EventDetailDto, EventDetai
.firedUpon(dto.getFiredUpon())
.eventStartDate(dto.getEventStartDate())
.eventEndDate(dto.getEventEndDate())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.cargoes(dto.getCargoes() != null ?
dto.getCargoes().stream().map(CargoDto::toEntity).collect(Collectors.toList()) : null)
dto.getCargoes().stream()
.map(d -> (CargoEntity) d.toEntity().setBatchInfo(jobExecutionId, "SYSTEM"))
.collect(Collectors.toList()) : null)
.humanCasualties(dto.getHumanCasualties() != null ?
dto.getHumanCasualties().stream().map(HumanCasualtyDto::toEntity).collect(Collectors.toList()) : null)
dto.getHumanCasualties().stream()
.map(d -> (HumanCasualtyEntity) d.toEntity().setBatchInfo(jobExecutionId, "SYSTEM"))
.collect(Collectors.toList()) : null)
.relationships(dto.getRelationships() != null ?
dto.getRelationships().stream().map(RelationshipDto::toEntity).collect(Collectors.toList()) : null)
dto.getRelationships().stream()
.map(d -> (RelationshipEntity) d.toEntity().setBatchInfo(jobExecutionId, "SYSTEM"))
.collect(Collectors.toList()) : null)
.build();
log.debug("Event 데이터 처리 완료: Event ID = {}", dto.getEventID());

파일 보기

@ -182,6 +182,8 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setString(idx++, entity.getVesselName()); // vessel_name (누락됨)
ps.setString(idx++, entity.getVesselType()); // vessel_type (누락됨)
ps.setString(idx++, entity.getVesselTypeDecode()); // vessel_type_decode
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
private void setCargoInsertParameters(PreparedStatement ps, CargoEntity entity)throws Exception{
int idx = 1;
@ -196,6 +198,8 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setString(idx++, entity.getCargoDamage());
ps.setString(idx++, entity.getDangerous());
ps.setString(idx++, entity.getText());
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
private void setHumanCasualtyInsertParameters(PreparedStatement ps, HumanCasualtyEntity entity)throws Exception{
int idx = 1;
@ -204,6 +208,8 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setString(idx++, entity.getType());
ps.setString(idx++, entity.getQualifier());
ps.setObject(idx++, entity.getCount());
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
private void setRelationshipInsertParameters(PreparedStatement ps, RelationshipEntity entity)throws Exception{
int idx = 1;
@ -214,6 +220,8 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setObject(idx++, entity.getEventID2());
ps.setString(idx++, entity.getEventType());
ps.setString(idx++, entity.getEventTypeCode());
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
private static void setStringOrNull(PreparedStatement ps, int index, String value) throws Exception {

파일 보기

@ -3,7 +3,7 @@ package com.snp.batch.jobs.event.batch.repository;
public class EventSql {
public static String getEventDetailUpdateSql(){
return """
INSERT INTO new_snp.event (
INSERT INTO t_snp_data.event (
event_id, incident_id, ihslrorimoshipno, published_date, event_start_date, event_end_date,
attempted_boarding, cargo_loading_status_code, casualty_action,
casualty_zone, casualty_zone_code, component2, country_code,
@ -14,109 +14,59 @@ public class EventSql {
pollutant_unit, registered_owner_code_at_time, registered_owner_at_time,
registered_owner_country_code_at_time, registered_owner_country_at_time,
vessel_dwt, vessel_flag_code, vessel_flag_decode, vessel_gt,
vessel_name, vessel_type, vessel_type_decode
vessel_name, vessel_type, vessel_type_decode,
job_execution_id, created_by
)
VALUES (
?, ?, ?, ?::timestamptz,?::timestamptz,?::timestamptz, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
ON CONFLICT (event_id)
DO UPDATE SET
incident_id = EXCLUDED.incident_id,
ihslrorimoshipno = EXCLUDED.ihslrorimoshipno,
published_date = EXCLUDED.published_date,
event_start_date = EXCLUDED.event_start_date,
event_end_date = EXCLUDED.event_end_date,
attempted_boarding = EXCLUDED.attempted_boarding,
cargo_loading_status_code = EXCLUDED.cargo_loading_status_code,
casualty_action = EXCLUDED.casualty_action,
casualty_zone = EXCLUDED.casualty_zone,
casualty_zone_code = EXCLUDED.casualty_zone_code,
component2 = EXCLUDED.component2,
country_code = EXCLUDED.country_code,
date_of_build = EXCLUDED.date_of_build,
description = EXCLUDED.description,
environment_location = EXCLUDED.environment_location,
location_name = EXCLUDED.location_name,
marsden_grid_reference = EXCLUDED.marsden_grid_reference,
town_name = EXCLUDED.town_name,
event_type = EXCLUDED.event_type,
event_type_detail = EXCLUDED.event_type_detail,
event_type_detail_id = EXCLUDED.event_type_detail_id,
event_type_id = EXCLUDED.event_type_id,
fired_upon = EXCLUDED.fired_upon,
headline = EXCLUDED.headline,
ldt_at_time = EXCLUDED.ldt_at_time,
significance = EXCLUDED.significance,
weather = EXCLUDED.weather,
pollutant = EXCLUDED.pollutant,
pollutant_quantity = EXCLUDED.pollutant_quantity,
pollutant_unit = EXCLUDED.pollutant_unit,
registered_owner_code_at_time = EXCLUDED.registered_owner_code_at_time,
registered_owner_at_time = EXCLUDED.registered_owner_at_time,
registered_owner_country_code_at_time = EXCLUDED.registered_owner_country_code_at_time,
registered_owner_country_at_time = EXCLUDED.registered_owner_country_at_time,
vessel_dwt = EXCLUDED.vessel_dwt,
vessel_flag_code = EXCLUDED.vessel_flag_code,
vessel_flag_decode = EXCLUDED.vessel_flag_decode,
vessel_gt = EXCLUDED.vessel_gt,
vessel_name = EXCLUDED.vessel_name,
vessel_type = EXCLUDED.vessel_type,
vessel_type_decode = EXCLUDED.vessel_type_decode
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?
);
""";
}
public static String getEventCargoSql(){
return """
INSERT INTO new_snp.event_cargo (
INSERT INTO t_snp_data.event_cargo (
event_id, "sequence", ihslrorimoshipno, "type", quantity,
unit_short, unit, cargo_damage, dangerous, "text"
unit_short, unit, cargo_damage, dangerous, "text",
job_execution_id, created_by
)
VALUES (
?, ?, ?, ?, ?,
?, ?, ?, ?, ?
)
ON CONFLICT (event_id, ihslrorimoshipno, "type", "sequence")
DO UPDATE SET
quantity = EXCLUDED.quantity,
unit_short = EXCLUDED.unit_short,
unit = EXCLUDED.unit,
cargo_damage = EXCLUDED.cargo_damage,
dangerous = EXCLUDED.dangerous,
"text" = EXCLUDED."text"
?, ?, ?, ?, ?,
?, ?
);
""";
}
public static String getEventRelationshipSql(){
return """
INSERT INTO new_snp.event_relationship (
INSERT INTO t_snp_data.event_relationship (
incident_id, event_id, relationship_type, relationship_type_code,
event_id_2, event_type, event_type_code
event_id_2, event_type, event_type_code,
job_execution_id, created_by
)
VALUES (
?, ?, ?, ?,
?, ?, ?
)
ON CONFLICT (incident_id, event_id, event_id_2, event_type_code, relationship_type_code)
DO UPDATE SET
relationship_type = EXCLUDED.relationship_type,
event_type = EXCLUDED.event_type
?, ?, ?,
?, ?
);
""";
}
public static String getEventHumanCasualtySql(){
return """
INSERT INTO new_snp.event_humancasualty (
event_id, "scope", "type", qualifier, "count"
INSERT INTO t_snp_data.event_humancasualty (
event_id, "scope", "type", qualifier, "count",
job_execution_id, created_by
)
VALUES (
?, ?, ?, ?, ?
)
ON CONFLICT (event_id, "scope", "type", qualifier)
DO UPDATE SET
"count" = EXCLUDED."count"
?, ?, ?, ?, ?,
?, ?
);
""";
}
}

파일 보기

@ -6,14 +6,17 @@ import com.snp.batch.jobs.facility.batch.entity.PortEntity;
import com.snp.batch.jobs.facility.batch.processor.PortDataProcessor;
import com.snp.batch.jobs.facility.batch.reader.PortDataReader;
import com.snp.batch.jobs.facility.batch.writer.PortDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@ -26,9 +29,12 @@ public class PortImportJobConfig extends BaseJobConfig<PortDto, PortEntity> {
private final JdbcTemplate jdbcTemplate;
private final WebClient maritimeServiceApiWebClient;
private final PortDataProcessor portDataProcessor;
private final PortDataWriter portDataWriter;
private final PortDataReader portDataReader;
private final BatchApiLogService batchApiLogService;
@Value("${app.batch.webservice-api.url}")
private String maritimeServiceApiUrl;
@Override
protected int getChunkSize() {
@ -37,46 +43,65 @@ public class PortImportJobConfig extends BaseJobConfig<PortDto, PortEntity> {
public PortImportJobConfig(
JobRepository jobRepository,
PlatformTransactionManager transactionManager,
PortDataProcessor portDataProcessor,
PortDataReader portDataReader,
PortDataWriter portDataWriter,
JdbcTemplate jdbcTemplate,
@Qualifier("maritimeServiceApiWebClient")WebClient maritimeServiceApiWebClient) {
@Qualifier("maritimeServiceApiWebClient")WebClient maritimeServiceApiWebClient,
BatchApiLogService batchApiLogService) {
super(jobRepository, transactionManager);
this.jdbcTemplate = jdbcTemplate;
this.maritimeServiceApiWebClient = maritimeServiceApiWebClient;
this.portDataProcessor = portDataProcessor;
this.portDataWriter = portDataWriter;
this.portDataReader = portDataReader;
this.batchApiLogService = batchApiLogService;
}
@Override
protected String getJobName() {
return "portImportJob";
return "PortImportJob";
}
@Override
protected String getStepName() {
return "portImportStep";
return "PortImportStep";
}
@Override
protected ItemReader<PortDto> createReader() {
return new PortDataReader(maritimeServiceApiWebClient, jdbcTemplate);
return portDataReader;
}
@Bean
@StepScope
public PortDataReader portDataReader(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId, // SpEL로 ID 추출
@Value("#{stepExecution.id}") Long stepExecutionId
) {
PortDataReader reader = new PortDataReader(maritimeServiceApiWebClient, jdbcTemplate, batchApiLogService, maritimeServiceApiUrl);
reader.setExecutionIds(jobExecutionId, stepExecutionId); // ID 세팅
return reader;
}
@Override
protected ItemProcessor<PortDto, PortEntity> createProcessor() {
return portDataProcessor;
// 2. 메서드 호출 방식으로 변경
return portDataProcessor(null);
}
@Bean
@StepScope
public PortDataProcessor portDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new PortDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<PortEntity> createWriter() { return portDataWriter; }
@Bean(name = "portImportJob")
@Bean(name = "PortImportJob")
public Job portImportJob() {
return job();
}
@Bean(name = "portImportStep")
@Bean(name = "PortImportStep")
public Step portImportStep() {
return step();
}

파일 보기

@ -4,11 +4,17 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.facility.batch.dto.PortDto;
import com.snp.batch.jobs.facility.batch.entity.PortEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class PortDataProcessor extends BaseProcessor<PortDto, PortEntity> {
private static Long jobExecutionId;
public PortDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
protected PortEntity processItem(PortDto dto) throws Exception {
log.debug("Port 데이터 처리 시작: Port ID = {}", dto.getPortId());
@ -71,6 +77,8 @@ public class PortDataProcessor extends BaseProcessor<PortDto, PortEntity> {
.freeTradeZone(dto.getFreeTradeZone())
.ecoPort(dto.getEcoPort())
.emissionControlArea(dto.getEmissionControlArea())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
log.debug("Port 데이터 처리 완료: Port ID = {}", dto.getPortId());

파일 보기

@ -3,6 +3,7 @@ package com.snp.batch.jobs.facility.batch.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
import com.snp.batch.jobs.facility.batch.dto.PortDto;
import com.snp.batch.jobs.shipimport.batch.dto.ShipApiResponse;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.jdbc.core.JdbcTemplate;
@ -17,11 +18,14 @@ public class PortDataReader extends BaseApiReader<PortDto> {
private final JdbcTemplate jdbcTemplate;
private List<String> allImoNumbers;
private int currentBatchIndex = 0;
private final int batchSize = 100;
public PortDataReader(WebClient webClient, JdbcTemplate jdbcTemplate) {
private final int batchSize = 5000;
private final BatchApiLogService batchApiLogService;
String maritimeServiceApiUrl;
public PortDataReader(WebClient webClient, JdbcTemplate jdbcTemplate, BatchApiLogService batchApiLogService, String maritimeServiceApiUrl) {
super(webClient);
this.jdbcTemplate = jdbcTemplate;
this.batchApiLogService = batchApiLogService;
this.maritimeServiceApiUrl = maritimeServiceApiUrl;
}
@Override
@ -57,13 +61,12 @@ public class PortDataReader extends BaseApiReader<PortDto> {
}
private List<PortDto> callFacilityPortApiWithBatch() {
String url = getApiPath();
log.debug("[{}] API 호출: {}", getReaderName(), url);
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<PortDto>>() {})
.block();
return executeListApiCall(
maritimeServiceApiUrl,
getApiPath(),
new ParameterizedTypeReference<List<PortDto>>() {},
batchApiLogService
);
}
}

파일 보기

@ -21,7 +21,7 @@ public class FacilityRepositoryImpl extends BaseJdbcRepository<PortEntity, Long>
@Override
protected String getTableName() {
return null;
return "t_snp_data.facility_port";
}
@Override
@ -42,73 +42,24 @@ public class FacilityRepositoryImpl extends BaseJdbcRepository<PortEntity, Long>
@Override
protected String getUpdateSql() {
return """
INSERT INTO snp_data.facility_port (
INSERT INTO %s(
port_ID, old_ID, status, port_Name, unlocode, countryCode, country_Name, region_Name, continent_Name, master_POID,
dec_Lat, dec_Long, position_lat, position_long, position_z, position_m, position_hasZ, position_hasM, position_isNull, position_stSrid, time_Zone, dayLight_Saving_Time,
maximum_Draft, max_LOA, max_Beam, max_DWT, max_Offshore_Draught, max_Offshore_LOA, max_Offshore_BCM, max_Offshore_DWT,
breakbulk_Facilities, container_Facilities, dry_Bulk_Facilities, liquid_Facilities, roRo_Facilities, passenger_Facilities, dry_Dock_Facilities,
lpG_Facilities, lnG_Facilities, lnG_Bunker, dO_Bunker, fO_Bunker, ispS_Compliant, csI_Compliant, free_Trade_Zone, ecO_Port, emission_Control_Area, wS_Port,
last_Update, entry_Date, batch_flag
last_Update, entry_Date,
job_execution_id, created_by
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?::timestamptz, ?::timestamptz, 'N'
) ON CONFLICT (port_ID) DO UPDATE
SET
old_ID = EXCLUDED.old_ID,
status = EXCLUDED.status,
port_Name = EXCLUDED.port_Name,
unlocode = EXCLUDED.unlocode,
countryCode = EXCLUDED.countryCode,
country_Name = EXCLUDED.country_Name,
region_Name = EXCLUDED.region_Name,
continent_Name = EXCLUDED.continent_Name,
master_POID = EXCLUDED.master_POID,
dec_Lat = EXCLUDED.dec_Lat,
dec_Long = EXCLUDED.dec_Long,
position_lat = EXCLUDED.position_lat,
position_long = EXCLUDED.position_long,
position_z = EXCLUDED.position_z,
position_m = EXCLUDED.position_m,
position_hasZ = EXCLUDED.position_hasZ,
position_hasM = EXCLUDED.position_hasM,
position_isNull = EXCLUDED.position_isNull,
position_stSrid = EXCLUDED.position_stSrid,
time_Zone = EXCLUDED.time_Zone,
dayLight_Saving_Time = EXCLUDED.dayLight_Saving_Time,
maximum_Draft = EXCLUDED.maximum_Draft,
max_LOA = EXCLUDED.max_LOA,
max_Beam = EXCLUDED.max_Beam,
max_DWT = EXCLUDED.max_DWT,
max_Offshore_Draught = EXCLUDED.max_Offshore_Draught,
max_Offshore_LOA = EXCLUDED.max_Offshore_LOA,
max_Offshore_BCM = EXCLUDED.max_Offshore_BCM,
max_Offshore_DWT = EXCLUDED.max_Offshore_DWT,
breakbulk_Facilities = EXCLUDED.breakbulk_Facilities,
container_Facilities = EXCLUDED.container_Facilities,
dry_Bulk_Facilities = EXCLUDED.dry_Bulk_Facilities,
liquid_Facilities = EXCLUDED.liquid_Facilities,
roRo_Facilities = EXCLUDED.roRo_Facilities,
passenger_Facilities = EXCLUDED.passenger_Facilities,
dry_Dock_Facilities = EXCLUDED.dry_Dock_Facilities,
lpG_Facilities = EXCLUDED.lpG_Facilities,
lnG_Facilities = EXCLUDED.lnG_Facilities,
lnG_Bunker = EXCLUDED.lnG_Bunker,
dO_Bunker = EXCLUDED.dO_Bunker,
fO_Bunker = EXCLUDED.fO_Bunker,
ispS_Compliant = EXCLUDED.ispS_Compliant,
csI_Compliant = EXCLUDED.csI_Compliant,
free_Trade_Zone = EXCLUDED.free_Trade_Zone,
ecO_Port = EXCLUDED.ecO_Port,
emission_Control_Area = EXCLUDED.emission_Control_Area,
wS_Port = EXCLUDED.wS_Port,
last_Update = EXCLUDED.last_Update,
entry_Date = EXCLUDED.entry_Date,
batch_flag = 'N'
""";
?::timestamptz, ?::timestamptz,
?, ?
);
""".formatted(getTableName());
}
@Override
@ -176,6 +127,8 @@ public class FacilityRepositoryImpl extends BaseJdbcRepository<PortEntity, Long>
setIntegerOrNull(ps, idx++, entity.getWsPort()); // 원본 위치: 마지막 부분 (INT8에 맞게 setLongOrNull 사용 가정)
ps.setString(idx++, entity.getLastUpdate()); // String 대신 Timestamp 타입이 JDBC 표준에 적합합니다.
ps.setString(idx++, entity.getEntryDate()); // String 대신 Timestamp 타입이 JDBC 표준에 적합합니다.
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
@ -39,12 +40,13 @@ public class AnchorageCallsRangeJobConfig extends BaseMultiStepJobConfig<Anchora
private final JdbcTemplate jdbcTemplate;
private final BatchDateService batchDateService;
private final BatchApiLogService batchApiLogService;
private final ObjectMapper objectMapper;
@Value("${app.batch.webservice-api.url}")
private String maritimeServiceApiUrl;
protected String getApiKey() {return "ANCHORAGE_CALLS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public AnchorageCallsRangeJobConfig(
@ -56,7 +58,8 @@ public class AnchorageCallsRangeJobConfig extends BaseMultiStepJobConfig<Anchora
@Qualifier("maritimeServiceApiWebClient")WebClient maritimeServiceApiWebClient,
JdbcTemplate jdbcTemplate,
BatchDateService batchDateService,
BatchApiLogService batchApiLogService
BatchApiLogService batchApiLogService,
ObjectMapper objectMapper
) {
super(jobRepository, transactionManager);
this.anchorageCallsProcessor = anchorageCallsProcessor;
@ -66,6 +69,7 @@ public class AnchorageCallsRangeJobConfig extends BaseMultiStepJobConfig<Anchora
this.jdbcTemplate = jdbcTemplate;
this.batchDateService = batchDateService;
this.batchApiLogService = batchApiLogService;
this.objectMapper = objectMapper;
}
@Override
@ -106,6 +110,14 @@ public class AnchorageCallsRangeJobConfig extends BaseMultiStepJobConfig<Anchora
protected ItemProcessor<AnchorageCallsDto, AnchorageCallsEntity> createProcessor() {
return anchorageCallsProcessor;
}
@Bean
@StepScope
public AnchorageCallsProcessor anchorageCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new AnchorageCallsProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<AnchorageCallsEntity> createWriter() { // 타입 변경

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.BerthCallsDto;
import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
@ -44,7 +45,7 @@ public class BerthCallsRangJobConfig extends BaseMultiStepJobConfig<BerthCallsDt
private String maritimeServiceApiUrl;
protected String getApiKey() {return "BERTH_CALLS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public BerthCallsRangJobConfig(
JobRepository jobRepository,
@ -104,6 +105,15 @@ public class BerthCallsRangJobConfig extends BaseMultiStepJobConfig<BerthCallsDt
return berthCallsProcessor;
}
@Bean
@StepScope
public BerthCallsProcessor berthCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new BerthCallsProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<BerthCallsEntity> createWriter() {
return berthCallsWriter;

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.CurrentlyAtDto;
import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
@ -44,7 +45,7 @@ public class CurrentlyAtRangeJobConfig extends BaseMultiStepJobConfig<CurrentlyA
private String maritimeServiceApiUrl;
protected String getApiKey() {return "CURRENTLY_AT_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public CurrentlyAtRangeJobConfig(
JobRepository jobRepository,
@ -103,7 +104,14 @@ public class CurrentlyAtRangeJobConfig extends BaseMultiStepJobConfig<CurrentlyA
protected ItemProcessor<CurrentlyAtDto, CurrentlyAtEntity> createProcessor() {
return currentlyAtProcessor;
}
@Bean
@StepScope
public CurrentlyAtProcessor currentlyAtProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new CurrentlyAtProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<CurrentlyAtEntity> createWriter() { // 타입 변경
return currentlyAtWriter;

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.DestinationDto;
import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
@ -32,8 +33,8 @@ import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class DestinationsRangeJobConfig extends BaseMultiStepJobConfig<DestinationDto, DestinationEntity> {
private final DestinationProcessor DestinationProcessor;
private final DestinationWriter DestinationWriter;
private final DestinationProcessor destinationProcessor;
private final DestinationWriter destinationWriter;
private final DestinationRangeReader destinationRangeReader;
private final WebClient maritimeApiWebClient;
private final JdbcTemplate jdbcTemplate;
@ -44,14 +45,14 @@ public class DestinationsRangeJobConfig extends BaseMultiStepJobConfig<Destinati
private String maritimeServiceApiUrl;
protected String getApiKey() {return "DESTINATIONS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public DestinationsRangeJobConfig(
JobRepository jobRepository,
PlatformTransactionManager transactionManager,
DestinationProcessor DestinationProcessor,
DestinationWriter DestinationWriter,
DestinationProcessor destinationProcessor,
DestinationWriter destinationWriter,
DestinationRangeReader destinationRangeReader,
@Qualifier("maritimeServiceApiWebClient") WebClient maritimeApiWebClient,
JdbcTemplate jdbcTemplate,
@ -59,8 +60,8 @@ public class DestinationsRangeJobConfig extends BaseMultiStepJobConfig<Destinati
BatchApiLogService batchApiLogService
) { // ObjectMapper 주입 추가
super(jobRepository, transactionManager);
this.DestinationProcessor = DestinationProcessor;
this.DestinationWriter = DestinationWriter;
this.destinationProcessor = destinationProcessor;
this.destinationWriter = destinationWriter;
this.destinationRangeReader = destinationRangeReader;
this.maritimeApiWebClient = maritimeApiWebClient;
this.jdbcTemplate = jdbcTemplate;
@ -102,12 +103,21 @@ public class DestinationsRangeJobConfig extends BaseMultiStepJobConfig<Destinati
}
@Override
protected ItemProcessor<DestinationDto, DestinationEntity> createProcessor() {
return DestinationProcessor;
return destinationProcessor;
}
@Bean
@StepScope
public DestinationProcessor destinationProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new DestinationProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<DestinationEntity> createWriter() { // 타입 변경
return DestinationWriter;
return destinationWriter;
}
@Override

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.PortCallsDto;
import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
@ -44,7 +45,7 @@ public class ShipPortCallsRangeJobConfig extends BaseMultiStepJobConfig<PortCall
private String maritimeServiceApiUrl;
protected String getApiKey() {return "PORT_CALLS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public ShipPortCallsRangeJobConfig(
JobRepository jobRepository,
@ -106,6 +107,15 @@ public class ShipPortCallsRangeJobConfig extends BaseMultiStepJobConfig<PortCall
return portCallsProcessor;
}
@Bean
@StepScope
public PortCallsProcessor portCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new PortCallsProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<PortCallsEntity> createWriter() { // 타입 변경
return portCallsWriter;

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.StsOperationDto;
import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
@ -44,7 +45,7 @@ public class StsOperationRangeJobConfig extends BaseMultiStepJobConfig<StsOperat
private String maritimeServiceApiUrl;
protected String getApiKey() {return "STS_OPERATION_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public StsOperationRangeJobConfig(
@ -104,6 +105,14 @@ public class StsOperationRangeJobConfig extends BaseMultiStepJobConfig<StsOperat
protected ItemProcessor<StsOperationDto, StsOperationEntity> createProcessor() {
return stsOperationProcessor;
}
@Bean
@StepScope
public StsOperationProcessor stsOperationProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new StsOperationProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<StsOperationEntity> createWriter() { // 타입 변경

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.movement.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.movement.batch.dto.TerminalCallsDto;
import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
@ -44,7 +45,7 @@ public class TerminalCallsRangeJobConfig extends BaseMultiStepJobConfig<Terminal
private String maritimeServiceApiUrl;
protected String getApiKey() {return "TERMINAL_CALLS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public TerminalCallsRangeJobConfig(
@ -104,6 +105,14 @@ public class TerminalCallsRangeJobConfig extends BaseMultiStepJobConfig<Terminal
protected ItemProcessor<TerminalCallsDto, TerminalCallsEntity> createProcessor() {
return terminalCallsProcessor;
}
@Bean
@StepScope
public TerminalCallsProcessor terminalCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper
) {
return new TerminalCallsProcessor(jobExecutionId, objectMapper);
}
@Override
protected ItemWriter<TerminalCallsEntity> createWriter() { // 타입 변경

파일 보기

@ -44,7 +44,7 @@ public class TransitsRangeJobConfig extends BaseMultiStepJobConfig<TransitsDto,
private String maritimeServiceApiUrl;
protected String getApiKey() {return "TRANSITS_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public TransitsRangeJobConfig(
JobRepository jobRepository,
@ -104,6 +104,14 @@ public class TransitsRangeJobConfig extends BaseMultiStepJobConfig<TransitsDto,
return transitsProcessor;
}
@Bean
@StepScope
public TransitsProcessor transitsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId
) {
return new TransitsProcessor(jobExecutionId);
}
@Override
protected ItemWriter<TransitsEntity> createWriter() { // 타입 변경
return transitsWriter;

파일 보기

@ -1,12 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -16,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class AnchorageCallsEntity {
@EqualsAndHashCode(callSuper = true)
public class AnchorageCallsEntity extends BaseEntity {
private Long id;

파일 보기

@ -1,12 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -16,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BerthCallsEntity {
@EqualsAndHashCode(callSuper = true)
public class BerthCallsEntity extends BaseEntity {
private Long id;

파일 보기

@ -1,12 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -16,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class CurrentlyAtEntity {
@EqualsAndHashCode(callSuper = true)
public class CurrentlyAtEntity extends BaseEntity {
private String movementType;
private String imolRorIHSNumber;
private LocalDateTime movementDate;

파일 보기

@ -1,8 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -12,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class DarkActivityEntity {
@EqualsAndHashCode(callSuper = true)
public class DarkActivityEntity extends BaseEntity {
private Long id;

파일 보기

@ -1,8 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -12,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class DestinationEntity {
@EqualsAndHashCode(callSuper = true)
public class DestinationEntity extends BaseEntity {
private String movementType;
private String imolRorIHSNumber;
private LocalDateTime movementDate;

파일 보기

@ -1,12 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -16,12 +14,9 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PortCallsEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ship_movement_id_seq")
@SequenceGenerator(name = "ship_movement_id_seq", sequenceName = "ship_movement_id_seq", allocationSize = 1)
@EqualsAndHashCode(callSuper = true)
public class PortCallsEntity extends BaseEntity {
private Long id;
private String movementType;
private String imolRorIHSNumber;
private LocalDateTime movementDate;

파일 보기

@ -1,8 +1,10 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -12,7 +14,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class StsOperationEntity {
@EqualsAndHashCode(callSuper = true)
public class StsOperationEntity extends BaseEntity {
private Long id;

파일 보기

@ -2,8 +2,10 @@ package com.snp.batch.jobs.movement.batch.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -13,7 +15,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class TerminalCallsEntity {
@EqualsAndHashCode(callSuper = true)
public class TerminalCallsEntity extends BaseEntity {
private Long id;

파일 보기

@ -1,7 +1,9 @@
package com.snp.batch.jobs.movement.batch.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -11,7 +13,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class TransitsEntity {
@EqualsAndHashCode(callSuper = true)
public class TransitsEntity extends BaseEntity {
private String movementType;
private String imolRorIHSNumber;
private LocalDateTime movementDate;

파일 보기

@ -6,33 +6,28 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class AnchorageCallsProcessor extends BaseProcessor<AnchorageCallsDto, AnchorageCallsEntity> {
private final ObjectMapper objectMapper;
public AnchorageCallsProcessor(ObjectMapper objectMapper) {
private final Long jobExecutionId;
public AnchorageCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected AnchorageCallsEntity processItem(AnchorageCallsDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("AnchorageCalls 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -60,6 +55,8 @@ public class AnchorageCallsProcessor extends BaseProcessor<AnchorageCallsDto, An
.destination(dto.getDestination())
.iso2(dto.getIso2())
.position(positionNode) // JsonNode로 매핑
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,33 +6,29 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.BerthCallsDto;
import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class BerthCallsProcessor extends BaseProcessor<BerthCallsDto, BerthCallsEntity> {
private final ObjectMapper objectMapper;
private final Long jobExecutionId;
public BerthCallsProcessor(ObjectMapper objectMapper) {
public BerthCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected BerthCallsEntity processItem(BerthCallsDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("BerthCalls 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -60,6 +56,8 @@ public class BerthCallsProcessor extends BaseProcessor<BerthCallsDto, BerthCalls
.parentCallId(dto.getParentCallId())
.iso2(dto.getIso2())
.eventStartDate(LocalDateTime.parse(dto.getEventStartDate()))
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,33 +6,29 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.CurrentlyAtDto;
import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class CurrentlyAtProcessor extends BaseProcessor<CurrentlyAtDto, CurrentlyAtEntity> {
private final ObjectMapper objectMapper;
private final Long jobExecutionId;
public CurrentlyAtProcessor(ObjectMapper objectMapper) {
public CurrentlyAtProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected CurrentlyAtEntity processItem(CurrentlyAtDto dto) throws Exception {
log.debug("Currently 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("CurrentlyAt 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -63,6 +59,8 @@ public class CurrentlyAtProcessor extends BaseProcessor<CurrentlyAtDto, Currentl
.destination(dto.getDestination())
.iso2(dto.getIso2())
.position(positionNode) // JsonNode로 매핑
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,33 +6,28 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.DestinationDto;
import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class DestinationProcessor extends BaseProcessor<DestinationDto, DestinationEntity> {
private final ObjectMapper objectMapper;
public DestinationProcessor(ObjectMapper objectMapper) {
private final Long jobExecutionId;
public DestinationProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected DestinationEntity processItem(DestinationDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("Destinations 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -54,6 +49,8 @@ public class DestinationProcessor extends BaseProcessor<DestinationDto, Destinat
.longitude(dto.getLongitude())
.position(positionNode) // JsonNode로 매핑
.iso2(dto.getIso2())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;
}

파일 보기

@ -6,33 +6,28 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.PortCallsDto;
import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class PortCallsProcessor extends BaseProcessor<PortCallsDto, PortCallsEntity> {
private final ObjectMapper objectMapper;
public PortCallsProcessor(ObjectMapper objectMapper) {
private final Long jobExecutionId;
public PortCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected PortCallsEntity processItem(PortCallsDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("PortCalls 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -63,7 +58,8 @@ public class PortCallsProcessor extends BaseProcessor<PortCallsDto, PortCallsEnt
.destination(dto.getDestination())
.iso2(dto.getIso2())
.position(positionNode) // JsonNode로 매핑
.schemaType("PORTCALL") // API 타입 구분
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,33 +6,28 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.StsOperationDto;
import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class StsOperationProcessor extends BaseProcessor<StsOperationDto, StsOperationEntity> {
private final ObjectMapper objectMapper;
public StsOperationProcessor(ObjectMapper objectMapper) {
private final Long jobExecutionId;
public StsOperationProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected StsOperationEntity processItem(StsOperationDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("StsOperations 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -61,6 +56,8 @@ public class StsOperationProcessor extends BaseProcessor<StsOperationDto, StsOpe
.stsLocation(dto.getStsLocation())
.stsType(dto.getStsType())
.eventStartDate(LocalDateTime.parse(dto.getEventStartDate()))
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -6,33 +6,29 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.TerminalCallsDto;
import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class TerminalCallsProcessor extends BaseProcessor<TerminalCallsDto, TerminalCallsEntity> {
private final ObjectMapper objectMapper;
private final Long jobExecutionId;
public TerminalCallsProcessor(ObjectMapper objectMapper) {
public TerminalCallsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId,
ObjectMapper objectMapper)
{
this.jobExecutionId = jobExecutionId;
this.objectMapper = objectMapper;
}
@Override
protected TerminalCallsEntity processItem(TerminalCallsDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("TerminalCalls 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
JsonNode positionNode = null;
@ -63,6 +59,8 @@ public class TerminalCallsProcessor extends BaseProcessor<TerminalCallsDto, Term
.subFacilityId(dto.getSubFacilityId())
.subFacilityName(dto.getSubFacilityName())
.subFacilityType(dto.getSubFacilityType())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;

파일 보기

@ -1,36 +1,30 @@
package com.snp.batch.jobs.movement.batch.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.movement.batch.dto.TransitsDto;
import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 선박 상세 정보 Processor
* ShipDetailDto ShipDetailEntity 변환
*/
/**
* 선박 상세 정보 Processor (해시 비교 증분 데이터 추출)
* I: ShipDetailComparisonData (DB 해시 + API Map Data)
* O: ShipDetailUpdate (변경분)
*/
@Slf4j
@Component
public class TransitsProcessor extends BaseProcessor<TransitsDto, TransitsEntity> {
// private final ObjectMapper objectMapper;
private final Long jobExecutionId;
// public TransitsProcessor(ObjectMapper objectMapper) {
// this.objectMapper = objectMapper;
// }
public TransitsProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId)
{
this.jobExecutionId = jobExecutionId;
}
@Override
protected TransitsEntity processItem(TransitsDto dto) throws Exception {
log.debug("선박 상세 정보 처리 시작: imoNumber={}, facilityName={}",
log.debug("Transits 정보 처리 시작: imoNumber={}, facilityName={}",
dto.getImolRorIHSNumber(), dto.getFacilityName());
TransitsEntity entity = TransitsEntity.builder()
@ -40,6 +34,8 @@ public class TransitsProcessor extends BaseProcessor<TransitsDto, TransitsEntity
.facilityName(dto.getFacilityName())
.facilityType(dto.getFacilityType())
.draught(dto.getDraught())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
return entity;
}

파일 보기

@ -1,6 +1,5 @@
package com.snp.batch.jobs.movement.batch.repository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
@ -10,15 +9,10 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("anchorageCallsRepository")
public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCallsEntity, String>
@ -30,8 +24,7 @@ public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCa
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_anchoragecall";
return "new_snp.t_anchoragecall";
return "t_snp_data.t_anchoragecall";
}
@Override
@ -46,10 +39,8 @@ public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCa
@Override
public String getInsertSql() {
/*return """
INSERT INTO snp_data.t_anchoragecall(*/
return """
INSERT INTO new_snp.t_anchoragecall(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -67,28 +58,10 @@ public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCa
lon,
dstn,
iso2_ntn_cd,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo,mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
stpov_id = EXCLUDED.stpov_id,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
lwrnk_fclty_id = EXCLUDED.lwrnk_fclty_id,
lwrnk_fclty_nm = EXCLUDED.lwrnk_fclty_nm,
lwrnk_fclty_type = EXCLUDED.lwrnk_fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
dstn = EXCLUDED.dstn,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -122,8 +95,8 @@ public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCa
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
// ps.setString(i++, e.getSchemaType());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@ -150,53 +123,7 @@ public class AnchorageCallsRepositoryImpl extends BaseJdbcRepository<AnchorageCa
public void saveAll(List<AnchorageCallsEntity> entities) {
if (entities == null || entities.isEmpty()) return;
// log.info("ShipMovement 저장 시작 = {}건", entities.size());
batchInsert(entities);
}
/**
* ShipDetailEntity RowMapper
*/
private static class AnchorageCallsRowMapper implements RowMapper<AnchorageCallsEntity> {
@Override
public AnchorageCallsEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
AnchorageCallsEntity entity = AnchorageCallsEntity.builder()
.id(rs.getLong("id"))
.imolRorIHSNumber(rs.getString("imolRorIHSNumber"))
.portCallId(rs.getObject("portCallId", Integer.class))
.facilityId(rs.getObject("facilityId", Integer.class))
.facilityName(rs.getString("facilityName"))
.facilityType(rs.getString("facilityType"))
.subFacilityId(rs.getObject("subFacilityId", Integer.class))
.subFacilityName(rs.getString("subFacilityName"))
.subFacilityType(rs.getString("subFacilityType"))
.countryCode(rs.getString("countryCode"))
.countryName(rs.getString("countryName"))
.draught(rs.getObject("draught", Double.class))
.latitude(rs.getObject("latitude", Double.class))
.longitude(rs.getObject("longitude", Double.class))
.destination(rs.getString("destination"))
.iso2(rs.getString("iso2"))
.position(parseJson(rs.getString("position")))
.build();
Timestamp movementDate = rs.getTimestamp("movementDate");
if (movementDate != null) {
entity.setMovementDate(movementDate.toLocalDateTime());
}
return entity;
}
private JsonNode parseJson(String json) {
try {
if (json == null) return null;
return new ObjectMapper().readTree(json);
} catch (Exception e) {
throw new RuntimeException("JSON 파싱 오류: " + json);
}
}
}
}

파일 보기

@ -1,6 +1,5 @@
package com.snp.batch.jobs.movement.batch.repository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
@ -10,15 +9,10 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("BerthCallsRepository")
public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntity, String>
@ -30,8 +24,7 @@ public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntit
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_berthcall";
return "new_snp.t_berthcall";
return "t_snp_data.t_berthcall";
}
@Override
@ -46,10 +39,8 @@ public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntit
@Override
public String getInsertSql() {
/*return """
INSERT INTO snp_data.t_berthcall(*/
return """
INSERT INTO new_snp.t_berthcall(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -67,28 +58,10 @@ public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntit
prnt_call_id,
iso2_ntn_cd,
evt_start_dt,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
up_fclty_id = EXCLUDED.up_fclty_id,
up_fclty_nm = EXCLUDED.up_fclty_nm,
up_fclty_type = EXCLUDED.up_fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
prnt_call_id = EXCLUDED.prnt_call_id,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
evt_start_dt = EXCLUDED.evt_start_dt,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -122,6 +95,8 @@ public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntit
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
private void setDoubleOrNull(PreparedStatement ps, int index, Double value) throws Exception {
@ -147,47 +122,7 @@ public class BerthCallsRepositoryImpl extends BaseJdbcRepository<BerthCallsEntit
public void saveAll(List<BerthCallsEntity> entities) {
if (entities == null || entities.isEmpty()) return;
// log.info("BerthCalls 저장 시작 = {}건", entities.size());
batchInsert(entities);
}
/**
* ShipDetailEntity RowMapper
*/
private static class BerthCallsRowMapper implements RowMapper<BerthCallsEntity> {
@Override
public BerthCallsEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
BerthCallsEntity entity = BerthCallsEntity.builder()
.id(rs.getLong("id"))
.imolRorIHSNumber(rs.getString("imolRorIHSNumber"))
.facilityId(rs.getObject("facilityId", Integer.class))
.facilityName(rs.getString("facilityName"))
.facilityType(rs.getString("facilityType"))
.countryCode(rs.getString("countryCode"))
.countryName(rs.getString("countryName"))
.draught(rs.getObject("draught", Double.class))
.latitude(rs.getObject("latitude", Double.class))
.longitude(rs.getObject("longitude", Double.class))
.position(parseJson(rs.getString("position")))
.build();
Timestamp movementDate = rs.getTimestamp("movementDate");
if (movementDate != null) {
entity.setMovementDate(movementDate.toLocalDateTime());
}
return entity;
}
private JsonNode parseJson(String json) {
try {
if (json == null) return null;
return new ObjectMapper().readTree(json);
} catch (Exception e) {
throw new RuntimeException("JSON 파싱 오류: " + json);
}
}
}
}

파일 보기

@ -10,12 +10,9 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("CurrentlyAtRepository")
public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEntity, String>
@ -27,8 +24,7 @@ public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEnt
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_currentlyat";
return "new_snp.t_currentlyat";
return "t_snp_data.t_currentlyat";
}
@Override
@ -43,10 +39,8 @@ public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEnt
@Override
public String getInsertSql() {
/*return """
INSERT INTO snp_data.t_currentlyat(*/
return """
INSERT INTO new_snp.t_currentlyat(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -67,31 +61,10 @@ public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEnt
lon,
dstn,
iso2_ntn_cd,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
stpov_id = EXCLUDED.stpov_id,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
lwrnk_fclty_id = EXCLUDED.lwrnk_fclty_id,
lwrnk_fclty_nm = EXCLUDED.lwrnk_fclty_nm,
lwrnk_fclty_type = EXCLUDED.lwrnk_fclty_type,
up_fclty_id = EXCLUDED.up_fclty_id,
up_fclty_nm = EXCLUDED.up_fclty_nm,
up_fclty_type = EXCLUDED.up_fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
dstn = EXCLUDED.dstn,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -128,8 +101,8 @@ public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEnt
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
// ps.setString(i++, e.getSchemaType());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@ -156,7 +129,6 @@ public class CurrentlyAtRepositoryImpl extends BaseJdbcRepository<CurrentlyAtEnt
public void saveAll(List<CurrentlyAtEntity> entities) {
if (entities == null || entities.isEmpty()) return;
// log.info("CurrentltAt 저장 시작 = {}건", entities.size());
batchInsert(entities);
}

파일 보기

@ -10,12 +10,9 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("DestinationRepository")
public class DestinationRepositoryImpl extends BaseJdbcRepository<DestinationEntity, String>
@ -27,8 +24,7 @@ public class DestinationRepositoryImpl extends BaseJdbcRepository<DestinationEnt
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_destination";
return "new_snp.t_destination";
return "t_snp_data.t_destination";
}
@Override
@ -46,7 +42,7 @@ public class DestinationRepositoryImpl extends BaseJdbcRepository<DestinationEnt
/*return """
INSERT INTO snp_data.t_destination(*/
return """
INSERT INTO new_snp.t_destination(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -58,22 +54,10 @@ public class DestinationRepositoryImpl extends BaseJdbcRepository<DestinationEnt
lat,
lon,
iso2_ntn_cd,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -101,6 +85,8 @@ public class DestinationRepositoryImpl extends BaseJdbcRepository<DestinationEnt
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
private void setDoubleOrNull(PreparedStatement ps, int index, Double value) throws Exception {

파일 보기

@ -4,13 +4,9 @@ import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
import java.util.List;
/**
* 선박 상세 정보 Repository 인터페이스
*/
public interface PortCallsRepository {
void saveAll(List<PortCallsEntity> entities);
boolean existsByPortCallId(Integer portCallId);
}

파일 보기

@ -1,6 +1,5 @@
package com.snp.batch.jobs.movement.batch.repository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
@ -10,15 +9,10 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("ShipMovementRepository")
public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity, String>
@ -30,8 +24,7 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_ship_stpov_info";
return "new_snp.t_ship_stpov_info";
return "t_snp_data.t_ship_stpov_info";
}
@Override
@ -46,10 +39,8 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
@Override
public String getInsertSql() {
// return """
// INSERT INTO snp_data.t_ship_stpov_info(
return """
INSERT INTO new_snp.t_ship_stpov_info(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -70,62 +61,15 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
lon,
dstn,
iso2_ntn_cd,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
stpov_id = EXCLUDED.stpov_id,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
lwrnk_fclty_id = EXCLUDED.lwrnk_fclty_id,
lwrnk_fclty_nm = EXCLUDED.lwrnk_fclty_nm,
lwrnk_fclty_type = EXCLUDED.lwrnk_fclty_type,
up_fclty_id = EXCLUDED.up_fclty_id,
up_fclty_nm = EXCLUDED.up_fclty_nm,
up_fclty_type = EXCLUDED.up_fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
dstn = EXCLUDED.dstn,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
protected String getUpdateSql() {
return """
UPDATE snp_data.t_ship_stpov_info
SET vesselid = ?,
maritimemobileserviceidentitymmsinumber = ?,
shipname = ?,
callsign = ?,
flagname = ?,
portofregistry = ?,
classificationsociety = ?,
shiptypelevel5 = ?,
shiptypelevel5subtype = ?,
yearofbuild = ?,
shipbuilder = ?,
lengthoverallloa = ?,
breadthmoulded = ?,
"depth" = ?,
draught = ?,
grosstonnage = ?,
deadweight = ?,
teu = ?,
speedservice = ?,
mainenginetype = ?,
status = ?,
operator = ?,
flagcode = ?,
shiptypelevel2 = ?
WHERE ihslrorimoshipno = ?
""";
return null;
}
@Override
@ -135,7 +79,6 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
ps.setString(i++, e.getMovementType()); // mvmn_type
ps.setTimestamp(i++, e.getMovementDate() != null ? Timestamp.valueOf(e.getMovementDate()) : null); // mvmn_dt
ps.setObject(i++, e.getPortCallId()); // stpov_id
// stpov_type는 'PORTCALL' 하드코딩되었으므로 세팅 안함
ps.setObject(i++, e.getFacilityId()); // fclty_id
ps.setString(i++, e.getFacilityName()); // fclty_nm
ps.setString(i++, e.getFacilityType()); // fclty_type
@ -158,8 +101,8 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
// ps.setString(i++, e.getSchemaType());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@ -179,7 +122,7 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
@Override
protected RowMapper<PortCallsEntity> getRowMapper() {
return new ShipMovementRowMapper();
return null;
}
@Override
@ -190,65 +133,4 @@ public class PortCallsRepositoryImpl extends BaseJdbcRepository<PortCallsEntity,
batchInsert(entities);
}
@Override
public boolean existsByPortCallId(Integer portCallId) {
String sql = """
SELECT COUNT(1)
FROM ship_movement
WHERE portCallId = ?
""";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, portCallId);
return count != null && count > 0;
}
/**
* ShipDetailEntity RowMapper
*/
private static class ShipMovementRowMapper implements RowMapper<PortCallsEntity> {
@Override
public PortCallsEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
PortCallsEntity entity = PortCallsEntity.builder()
.id(rs.getLong("id"))
.imolRorIHSNumber(rs.getString("imolRorIHSNumber"))
.portCallId(rs.getObject("portCallId", Integer.class))
.facilityId(rs.getObject("facilityId", Integer.class))
.facilityName(rs.getString("facilityName"))
.facilityType(rs.getString("facilityType"))
.subFacilityId(rs.getObject("subFacilityId", Integer.class))
.subFacilityName(rs.getString("subFacilityName"))
.subFacilityType(rs.getString("subFacilityType"))
.parentFacilityId(rs.getObject("parentFacilityId", Integer.class))
.parentFacilityName(rs.getString("parentFacilityName"))
.parentFacilityType(rs.getString("parentFacilityType"))
.countryCode(rs.getString("countryCode"))
.countryName(rs.getString("countryName"))
.draught(rs.getObject("draught", Double.class))
.latitude(rs.getObject("latitude", Double.class))
.longitude(rs.getObject("longitude", Double.class))
.destination(rs.getString("destination"))
.iso2(rs.getString("iso2"))
.position(parseJson(rs.getString("position")))
.schemaType(rs.getString("schemaType"))
.build();
Timestamp movementDate = rs.getTimestamp("movementDate");
if (movementDate != null) {
entity.setMovementDate(movementDate.toLocalDateTime());
}
return entity;
}
private JsonNode parseJson(String json) {
try {
if (json == null) return null;
return new com.fasterxml.jackson.databind.ObjectMapper().readTree(json);
} catch (Exception e) {
throw new RuntimeException("JSON 파싱 오류: " + json);
}
}
}
}

파일 보기

@ -10,12 +10,9 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("StsOperationRepository")
public class StsOperationRepositoryImpl extends BaseJdbcRepository<StsOperationEntity, String>
@ -27,8 +24,7 @@ public class StsOperationRepositoryImpl extends BaseJdbcRepository<StsOperationE
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_stsoperation";
return "new_snp.t_stsoperation";
return "t_snp_data.t_stsoperation";
}
@Override
@ -43,10 +39,8 @@ public class StsOperationRepositoryImpl extends BaseJdbcRepository<StsOperationE
@Override
public String getInsertSql() {
// return """
// INSERT INTO snp_data.t_stsoperation(
return """
INSERT INTO new_snp.t_stsoperation(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -65,29 +59,10 @@ public class StsOperationRepositoryImpl extends BaseJdbcRepository<StsOperationE
sts_location,
sts_type,
evt_start_dt,
lcinfo
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt, fclty_id)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
up_fclty_id = EXCLUDED.up_fclty_id,
up_fclty_nm = EXCLUDED.up_fclty_nm,
up_fclty_type = EXCLUDED.up_fclty_type,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
prnt_call_id = EXCLUDED.prnt_call_id,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
sts_location = EXCLUDED.sts_location,
sts_type = EXCLUDED.sts_type,
evt_start_dt = EXCLUDED.evt_start_dt,
lcinfo = EXCLUDED.lcinfo
""";
lcinfo,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -122,6 +97,8 @@ public class StsOperationRepositoryImpl extends BaseJdbcRepository<StsOperationE
} else {
ps.setNull(i++, java.sql.Types.OTHER);
}
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
private void setDoubleOrNull(PreparedStatement ps, int index, Double value) throws Exception {

파일 보기

@ -10,12 +10,9 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("TerminalCallsRepository")
public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCallsEntity, String>
@ -27,8 +24,7 @@ public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCall
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_terminalcall";
return "new_snp.t_terminalcall";
return "t_snp_data.t_terminalcall";
}
@Override
@ -46,7 +42,7 @@ public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCall
// return """
// INSERT INTO snp_data.t_terminalcall(
return """
INSERT INTO new_snp.t_terminalcall(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
@ -67,31 +63,10 @@ public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCall
lcinfo,
sub_fclty_id,
sub_fclty_nm,
sub_fclty_type
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
fclty_id = EXCLUDED.fclty_id,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
up_fclty_id = EXCLUDED.up_fclty_id,
up_fclty_nm = EXCLUDED.up_fclty_nm,
up_fclty_type = EXCLUDED.up_fclty_type,
ntn_cd = EXCLUDED.ntn_cd,
ntn_nm = EXCLUDED.ntn_nm,
draft = EXCLUDED.draft,
lat = EXCLUDED.lat,
lon = EXCLUDED.lon,
prnt_call_id = EXCLUDED.prnt_call_id,
iso2_ntn_cd = EXCLUDED.iso2_ntn_cd,
evt_start_dt = EXCLUDED.evt_start_dt,
lcinfo = EXCLUDED.lcinfo,
sub_fclty_id = EXCLUDED.sub_fclty_id,
sub_fclty_nm = EXCLUDED.sub_fclty_nm,
sub_fclty_type = EXCLUDED.sub_fclty_type
""";
sub_fclty_type,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -128,6 +103,8 @@ public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCall
ps.setObject(i++, e.getSubFacilityId());
ps.setString(i++, e.getSubFacilityName());
ps.setString(i++, e.getSubFacilityType());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
private void setDoubleOrNull(PreparedStatement ps, int index, Double value) throws Exception {
@ -153,7 +130,6 @@ public class TerminalCallsRepositoryImpl extends BaseJdbcRepository<TerminalCall
public void saveAll(List<TerminalCallsEntity> entities) {
if (entities == null || entities.isEmpty()) return;
// log.info("TerminallCalls 저장 시작 = {}건", entities.size());
batchInsert(entities);
}

파일 보기

@ -10,12 +10,9 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
/**
* 선박 상세 정보 Repository 구현체
* BaseJdbcRepository를 상속하여 JDBC 기반 CRUD 구현
*/
@Slf4j
@Repository("TransitsRepository")
public class TransitsRepositoryImpl extends BaseJdbcRepository<TransitsEntity, String>
@ -27,8 +24,7 @@ public class TransitsRepositoryImpl extends BaseJdbcRepository<TransitsEntity, S
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
protected String getTableName() {
// return "snp_data.t_transit";
return "new_snp.t_transit";
return "t_snp_data.t_transit";
}
@Override
@ -43,25 +39,17 @@ public class TransitsRepositoryImpl extends BaseJdbcRepository<TransitsEntity, S
@Override
public String getInsertSql() {
// return """
// INSERT INTO snp_data.t_transit(
return """
INSERT INTO new_snp.t_transit(
INSERT INTO %s(
imo,
mvmn_type,
mvmn_dt,
fclty_nm,
fclty_type,
draft
) VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (imo, mvmn_type, mvmn_dt)
DO UPDATE SET
mvmn_type = EXCLUDED.mvmn_type,
mvmn_dt = EXCLUDED.mvmn_dt,
fclty_nm = EXCLUDED.fclty_nm,
fclty_type = EXCLUDED.fclty_type,
draft = EXCLUDED.draft
""";
draft,
job_execution_id, created_by
) VALUES (?, ?, ?, ?, ?, ?, ?, ?);
""".formatted(getTableName());
}
@Override
@ -78,6 +66,8 @@ public class TransitsRepositoryImpl extends BaseJdbcRepository<TransitsEntity, S
ps.setString(i++, e.getFacilityName()); // fclty_nm
ps.setString(i++, e.getFacilityType()); // fclty_type
setDoubleOrNull(ps, i++, e.getDraught()); // draft
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
private void setDoubleOrNull(PreparedStatement ps, int index, Double value) throws Exception {

파일 보기

@ -1,6 +1,8 @@
package com.snp.batch.jobs.pscInspection.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.facility.batch.processor.PortDataProcessor;
import com.snp.batch.jobs.pscInspection.batch.dto.PscInspectionDto;
import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
import com.snp.batch.jobs.pscInspection.batch.processor.PscInspectionProcessor;
@ -31,7 +33,6 @@ import org.springframework.web.reactive.function.client.WebClient;
@Slf4j
@Configuration
public class PscInspectionJobConfig extends BaseMultiStepJobConfig<PscInspectionDto, PscInspectionEntity> {
private final PscInspectionProcessor pscInspectionProcessor;
private final PscInspectionWriter pscInspectionWriter;
private final PscApiReader pscApiReader;
@ -44,7 +45,7 @@ public class PscInspectionJobConfig extends BaseMultiStepJobConfig<PscInspection
private String maritimeApiUrl;
protected String getApiKey() {return "PSC_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public PscInspectionJobConfig(
JobRepository jobRepository,
@ -107,6 +108,14 @@ public class PscInspectionJobConfig extends BaseMultiStepJobConfig<PscInspection
return pscInspectionProcessor;
}
@Bean
@StepScope
public PscInspectionProcessor pscInspectionProcessor(
ObjectMapper objectMapper,
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new PscInspectionProcessor(objectMapper, jobExecutionId);
}
@Override
protected ItemWriter<PscInspectionEntity> createWriter() { // 타입 변경
return pscInspectionWriter;

파일 보기

@ -1,7 +1,9 @@
package com.snp.batch.jobs.pscInspection.batch.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -11,7 +13,8 @@ import java.time.LocalDateTime;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PscAllCertificateEntity {
@EqualsAndHashCode(callSuper = true)
public class PscAllCertificateEntity extends BaseEntity {
private String certificateId;

파일 보기

@ -1,7 +1,9 @@
package com.snp.batch.jobs.pscInspection.batch.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -9,7 +11,8 @@ import lombok.experimental.SuperBuilder;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PscDefectEntity {
@EqualsAndHashCode(callSuper = true)
public class PscDefectEntity extends BaseEntity {
private String defectId;

파일 보기

@ -1,10 +1,9 @@
package com.snp.batch.jobs.pscInspection.batch.entity;
import com.snp.batch.jobs.pscInspection.batch.dto.PscAllCertificateDto;
import com.snp.batch.jobs.pscInspection.batch.dto.PscCertificateDto;
import com.snp.batch.jobs.pscInspection.batch.dto.PscDefectDto;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -16,7 +15,8 @@ import java.util.List;
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PscInspectionEntity {
@EqualsAndHashCode(callSuper = true)
public class PscInspectionEntity extends BaseEntity {
private String typeId;
private String dataSetVersion;

파일 보기

@ -1,12 +1,17 @@
package com.snp.batch.jobs.pscInspection.batch.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.pscInspection.batch.dto.*;
import com.snp.batch.jobs.pscInspection.batch.dto.PscAllCertificateDto;
import com.snp.batch.jobs.pscInspection.batch.dto.PscCertificateDto;
import com.snp.batch.jobs.pscInspection.batch.dto.PscDefectDto;
import com.snp.batch.jobs.pscInspection.batch.dto.PscInspectionDto;
import com.snp.batch.jobs.pscInspection.batch.entity.PscAllCertificateEntity;
import com.snp.batch.jobs.pscInspection.batch.entity.PscCertificateEntity;
import com.snp.batch.jobs.pscInspection.batch.entity.PscDefectEntity;
import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@ -15,17 +20,21 @@ import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static jakarta.xml.bind.DatatypeConverter.parseDateTime;
@Slf4j
@Component
public class PscInspectionProcessor extends BaseProcessor<PscInspectionDto, PscInspectionEntity> {
private static Long jobExecutionId;
private final ObjectMapper objectMapper;
public PscInspectionProcessor(
ObjectMapper objectMapper,
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.objectMapper = objectMapper;
this.jobExecutionId = jobExecutionId;
}
@Override
public PscInspectionEntity processItem(PscInspectionDto item) throws Exception {
@ -71,6 +80,8 @@ public class PscInspectionProcessor extends BaseProcessor<PscInspectionDto, PscI
entity.setSource(s(item.getSource()));
entity.setUnlocode(s(item.getUnlocode()));
entity.setYearOfBuild(s(item.getYearOfBuild()));
entity.setJobExecutionId(jobExecutionId);
entity.setCreatedBy("SYSTEM");
// 리스트 null-safe
entity.setDefects(item.getPscDefects() == null ? List.of() : convertDefectDtos(item.getPscDefects()));
@ -182,6 +193,8 @@ public class PscInspectionProcessor extends BaseProcessor<PscInspectionDto, PscI
.recognisedOrgRespCode(dto.getRecognisedOrgRespCode())
.recognisedOrgRespYn(dto.getRecognisedOrgRespYn())
.isAccidentalDamage(dto.getIsAccidentalDamage())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build())
.collect(Collectors.toList());
}
@ -241,6 +254,8 @@ public class PscInspectionProcessor extends BaseProcessor<PscInspectionDto, PscI
.surveyAuthorityType(dto.getSurveyAuthorityType())
.inspectionDate(dto.getInspectionDate())
.inspectedBy(dto.getInspectedBy())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build())
.collect(Collectors.toList());
}

파일 보기

@ -10,6 +10,7 @@ import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
@Slf4j
@ -43,7 +44,7 @@ public class PscAllCertificateRepositoryImpl extends BaseJdbcRepository<PscAllCe
@Override
public String getInsertSql() {
return """
INSERT INTO new_snp.psc_all_certificate(
INSERT INTO t_snp_data.psc_all_certificate(
certificate_id,
data_set_version,
inspection_id,
@ -63,32 +64,13 @@ public class PscAllCertificateRepositoryImpl extends BaseJdbcRepository<PscAllCe
latest_survey_place_code,
survey_authority_type,
inspection_date,
inspected_by
inspected_by,
job_execution_id, created_by
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
ON CONFLICT (certificate_id)
DO UPDATE SET
data_set_version = EXCLUDED.data_set_version,
inspection_id = EXCLUDED.inspection_id,
lrno = EXCLUDED.lrno,
certificate_title_code = EXCLUDED.certificate_title_code,
certificate_title = EXCLUDED.certificate_title,
issuing_authority_code = EXCLUDED.issuing_authority_code,
issuing_authority = EXCLUDED.issuing_authority,
other_issuing_authority = EXCLUDED.other_issuing_authority,
issue_date = EXCLUDED.issue_date,
expiry_date = EXCLUDED.expiry_date,
last_survey_date = EXCLUDED.last_survey_date,
survey_authority_code = EXCLUDED.survey_authority_code,
survey_authority = EXCLUDED.survey_authority,
other_survey_authority = EXCLUDED.other_survey_authority,
latest_survey_place = EXCLUDED.latest_survey_place,
latest_survey_place_code = EXCLUDED.latest_survey_place_code,
survey_authority_type = EXCLUDED.survey_authority_type,
inspection_date = EXCLUDED.inspection_date,
inspected_by = EXCLUDED.inspected_by
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?
);
""";
}
@ -122,6 +104,8 @@ public class PscAllCertificateRepositoryImpl extends BaseJdbcRepository<PscAllCe
ps.setString(i++, e.getSurveyAuthorityType());
ps.setString(i++, e.getInspectionDate());
ps.setString(i++, e.getInspectedBy());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@Override

파일 보기

@ -44,7 +44,7 @@ public class PscDefectRepositoryImpl extends BaseJdbcRepository<PscDefectEntity,
@Override
public String getInsertSql() {
return """
INSERT INTO new_snp.psc_defect(
INSERT INTO t_snp_data.psc_defect(
defect_id,
inspection_id,
data_set_version,
@ -68,37 +68,14 @@ public class PscDefectRepositoryImpl extends BaseJdbcRepository<PscDefectEntity,
recognised_org_resp,
recognised_org_resp_code,
recognised_org_resp_yn,
is_accidental_damage
is_accidental_damage,
job_execution_id, created_by
) VALUES (
?,?,?,?,?,?,?,?,?,?,
?,?,?,?,?,?,?,?,?,?,
?,?,?,?
)
ON CONFLICT (defect_id)
DO UPDATE SET
inspection_id = EXCLUDED.inspection_id,
data_set_version = EXCLUDED.data_set_version,
action_1 = EXCLUDED.action_1,
action_2 = EXCLUDED.action_2,
action_3 = EXCLUDED.action_3,
action_code_1 = EXCLUDED.action_code_1,
action_code_2 = EXCLUDED.action_code_2,
action_code_3 = EXCLUDED.action_code_3,
class_is_responsible = EXCLUDED.class_is_responsible,
defect_code = EXCLUDED.defect_code,
defect_text = EXCLUDED.defect_text,
defective_item_code = EXCLUDED.defective_item_code,
detention_reason_deficiency = EXCLUDED.detention_reason_deficiency,
main_defect_code = EXCLUDED.main_defect_code,
main_defect_text = EXCLUDED.main_defect_text,
nature_of_defect_code = EXCLUDED.nature_of_defect_code,
nature_of_defect_decode = EXCLUDED.nature_of_defect_decode,
other_action = EXCLUDED.other_action,
other_recognised_org_resp = EXCLUDED.other_recognised_org_resp,
recognised_org_resp = EXCLUDED.recognised_org_resp,
recognised_org_resp_code = EXCLUDED.recognised_org_resp_code,
recognised_org_resp_yn = EXCLUDED.recognised_org_resp_yn,
is_accidental_damage = EXCLUDED.is_accidental_damage
?,?,?,?,
?,?
);
""";
}
@ -136,6 +113,8 @@ public class PscDefectRepositoryImpl extends BaseJdbcRepository<PscDefectEntity,
ps.setString(i++, e.getRecognisedOrgRespCode());
ps.setString(i++, e.getRecognisedOrgRespYn());
ps.setString(i++, e.getIsAccidentalDamage());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@Override

파일 보기

@ -38,7 +38,7 @@ public class PscInspectionRepositoryImpl extends BaseJdbcRepository<PscInspectio
@Override
public String getInsertSql() {
return """
INSERT INTO new_snp.psc_detail(
INSERT INTO t_snp_data.psc_detail(
inspection_id,
data_set_version,
authorisation,
@ -68,43 +68,14 @@ public class PscInspectionRepositoryImpl extends BaseJdbcRepository<PscInspectio
ship_type_decode,
source,
unlocode,
year_of_build
year_of_build,
job_execution_id, created_by
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
ON CONFLICT (inspection_id)
DO UPDATE SET
data_set_version = EXCLUDED.data_set_version,
authorisation = EXCLUDED.authorisation,
call_sign = EXCLUDED.call_sign,
class = EXCLUDED.class,
charterer = EXCLUDED.charterer,
country = EXCLUDED.country,
inspection_date = EXCLUDED.inspection_date,
release_date = EXCLUDED.release_date,
ship_detained = EXCLUDED.ship_detained,
dead_weight = EXCLUDED.dead_weight,
expanded_inspection = EXCLUDED.expanded_inspection,
flag = EXCLUDED.flag,
follow_up_inspection = EXCLUDED.follow_up_inspection,
gross_tonnage = EXCLUDED.gross_tonnage,
inspection_port_decode = EXCLUDED.inspection_port_decode,
last_updated = EXCLUDED.last_updated,
ihslr_or_imo_ship_no = EXCLUDED.ihslr_or_imo_ship_no,
manager = EXCLUDED.manager,
number_of_days_detained = EXCLUDED.number_of_days_detained,
number_of_defects = EXCLUDED.number_of_defects,
number_of_part_days_detained = EXCLUDED.number_of_part_days_detained,
other_inspection_type = EXCLUDED.other_inspection_type,
owner = EXCLUDED.owner,
ship_name = EXCLUDED.ship_name,
ship_type_code = EXCLUDED.ship_type_code,
ship_type_decode = EXCLUDED.ship_type_decode,
source = EXCLUDED.source,
unlocode = EXCLUDED.unlocode,
year_of_build = EXCLUDED.year_of_build
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?
);
""";
}
@ -147,6 +118,8 @@ public class PscInspectionRepositoryImpl extends BaseJdbcRepository<PscInspectio
ps.setString(i++, e.getSource());
ps.setString(i++, e.getUnlocode());
ps.setString(i++, e.getYearOfBuild());
ps.setObject(i++, e.getJobExecutionId(), Types.INTEGER);
ps.setString(i++, e.getCreatedBy());
}
@Override

파일 보기

@ -44,7 +44,7 @@ public class RiskImportRangeJobConfig extends BaseMultiStepJobConfig<RiskDto, Ri
protected String getApiKey() {return "RISK_IMPORT_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
@Override
@ -108,6 +108,12 @@ public class RiskImportRangeJobConfig extends BaseMultiStepJobConfig<RiskDto, Ri
protected ItemProcessor<RiskDto, RiskEntity> createProcessor() {
return riskDataProcessor;
}
@Bean
@StepScope
public RiskDataProcessor riskDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
return new RiskDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<RiskEntity> createWriter() { return riskDataWriter; }

파일 보기

@ -4,11 +4,16 @@ import com.snp.batch.common.batch.processor.BaseProcessor;
import com.snp.batch.jobs.risk.batch.dto.RiskDto;
import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RiskDataProcessor extends BaseProcessor<RiskDto, RiskEntity> {
private final Long jobExecutionId;
public RiskDataProcessor(@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
@Override
protected RiskEntity processItem(RiskDto dto) throws Exception {
log.debug("Risk 데이터 처리 시작: imoNumber={}", dto.getLrno());
@ -113,6 +118,8 @@ public class RiskDataProcessor extends BaseProcessor<RiskDto, RiskEntity> {
.russianOwnerRegistrationNarrative(dto.getRussianOwnerRegistrationNarrative())
.russianSTS(dto.getRussianSTS())
.russianSTSNarrative(dto.getRussianSTSNarrative())
.jobExecutionId(jobExecutionId)
.createdBy("SYSTEM")
.build();
log.debug("Risk 데이터 처리 완료: imoNumber={}", dto.getLrno());

파일 보기

@ -6,5 +6,5 @@ import java.util.List;
public interface RiskRepository {
void saveRiskAll(List<RiskEntity> items);
void saveRiskHistoryAll(List<RiskEntity> items);
// void saveRiskHistoryAll(List<RiskEntity> items);
}

파일 보기

@ -8,6 +8,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.List;
@Slf4j
@ -20,7 +21,7 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
@Override
protected String getTableName() {
return null;
return "t_snp_data.risk";
}
@Override
@ -40,12 +41,8 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
@Override
protected String getUpdateSql() {
return null;
}
protected String getUpdateSql(String targetTable, String targetIndex) {
return """
INSERT INTO new_snp.%s (
INSERT INTO %s(
lrno, lastupdated,
riskdatamaintained, dayssincelastseenonais, daysunderais, imocorrectonais, sailingundername,
anomalousmessagesfrommmsi, mostrecentdarkactivity, portcalls, portrisk, stsoperations,
@ -54,7 +51,8 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
pscdetentions, currentsmccertificate, docchanges, currentclass, classstatuschanges,
pandicoverage, namechanges, gbochanges, ageofship, iuufishingviolation,
draughtchanges, mostrecentsanctionedportcall, singleshipoperation, fleetsafety, fleetpsc,
specialsurveyoverdue, ownerunknown, russianportcall, russianownerregistration, russiansts
specialsurveyoverdue, ownerunknown, russianportcall, russianownerregistration, russiansts,
job_execution_id, created_by
)
VALUES (
?, ?::timestamptz,
@ -65,51 +63,10 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?
)
ON CONFLICT (%s)
DO UPDATE SET
riskdatamaintained = EXCLUDED.riskdatamaintained,
dayssincelastseenonais = EXCLUDED.dayssincelastseenonais,
daysunderais = EXCLUDED.daysunderais,
imocorrectonais = EXCLUDED.imocorrectonais,
sailingundername = EXCLUDED.sailingundername,
anomalousmessagesfrommmsi = EXCLUDED.anomalousmessagesfrommmsi,
mostrecentdarkactivity = EXCLUDED.mostrecentdarkactivity,
portcalls = EXCLUDED.portcalls,
portrisk = EXCLUDED.portrisk,
stsoperations = EXCLUDED.stsoperations,
driftinghighseas = EXCLUDED.driftinghighseas,
riskevents = EXCLUDED.riskevents,
flagchanges = EXCLUDED.flagchanges,
flagparismouperformance = EXCLUDED.flagparismouperformance,
flagtokyomoupeformance = EXCLUDED.flagtokyomoupeformance,
flaguscgmouperformance = EXCLUDED.flaguscgmouperformance,
uscgqualship21 = EXCLUDED.uscgqualship21,
timesincepscinspection = EXCLUDED.timesincepscinspection,
pscinspections = EXCLUDED.pscinspections,
pscdefects = EXCLUDED.pscdefects,
pscdetentions = EXCLUDED.pscdetentions,
currentsmccertificate = EXCLUDED.currentsmccertificate,
docchanges = EXCLUDED.docchanges,
currentclass = EXCLUDED.currentclass,
classstatuschanges = EXCLUDED.classstatuschanges,
pandicoverage = EXCLUDED.pandicoverage,
namechanges = EXCLUDED.namechanges,
gbochanges = EXCLUDED.gbochanges,
ageofship = EXCLUDED.ageofship,
iuufishingviolation = EXCLUDED.iuufishingviolation,
draughtchanges = EXCLUDED.draughtchanges,
mostrecentsanctionedportcall = EXCLUDED.mostrecentsanctionedportcall,
singleshipoperation = EXCLUDED.singleshipoperation,
fleetsafety = EXCLUDED.fleetsafety,
fleetpsc = EXCLUDED.fleetpsc,
specialsurveyoverdue = EXCLUDED.specialsurveyoverdue,
ownerunknown = EXCLUDED.ownerunknown,
russianportcall = EXCLUDED.russianportcall,
russianownerregistration = EXCLUDED.russianownerregistration,
russiansts = EXCLUDED.russiansts
""".formatted(targetTable, targetIndex);
?, ?, ?, ?, ?,
?, ?
);
""".formatted(getTableName());
}
@Override
@ -162,6 +119,8 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
ps.setObject(idx++, entity.getRussianPortCall(), java.sql.Types.INTEGER);
ps.setObject(idx++, entity.getRussianOwnerRegistration(), java.sql.Types.INTEGER);
ps.setObject(idx++, entity.getRussianSTS(), java.sql.Types.INTEGER);
ps.setObject(idx++, entity.getJobExecutionId(), Types.INTEGER);
ps.setString(idx++, entity.getCreatedBy());
}
@Override
@ -174,7 +133,7 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("risk", "lrno"), items, items.size(),
jdbcTemplate.batchUpdate(getUpdateSql(), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);
@ -187,21 +146,4 @@ public class RiskRepositoryImpl extends BaseJdbcRepository<RiskEntity, Long> imp
log.info("{} 전체 저장 완료: 수정={} 건", getEntityName(), items.size());
}
@Override
public void saveRiskHistoryAll(List<RiskEntity> items) {
if (items == null || items.isEmpty()) {
return;
}
jdbcTemplate.batchUpdate(getUpdateSql("risk_history", "lrno, lastupdated"), items, items.size(),
(ps, entity) -> {
try {
setUpdateParameters(ps, entity);
} catch (Exception e) {
log.error("배치 수정 파라미터 설정 실패", e);
throw new RuntimeException(e);
}
});
log.info("{} 전체 저장 완료: 수정={} 건", getEntityName(), items.size());
}
}

파일 보기

@ -19,6 +19,6 @@ public class RiskDataWriter extends BaseWriter<RiskEntity> {
@Override
protected void writeItems(List<RiskEntity> items) throws Exception {
riskRepository.saveRiskAll(items);
riskRepository.saveRiskHistoryAll(items);
// riskRepository.saveRiskHistoryAll(items);
}
}

파일 보기

@ -1,8 +1,9 @@
package com.snp.batch.jobs.shipdetail.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseJobConfig;
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailComparisonData; // Reader 출력 타입
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailUpdate; // Processor 출력 타입
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailDto;
import com.snp.batch.jobs.shipdetail.batch.entity.ShipDetailEntity;
import com.snp.batch.jobs.shipdetail.batch.processor.ShipDetailDataProcessor;
import com.snp.batch.jobs.shipdetail.batch.reader.ShipDetailDataReader;
import com.snp.batch.jobs.shipdetail.batch.writer.ShipDetailDataWriter;
@ -19,7 +20,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.reactive.function.client.WebClient;
import com.fasterxml.jackson.databind.ObjectMapper; // ObjectMapper 추가
/**
* 선박 상세 정보 Import Job Config
@ -27,8 +27,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; // ObjectMapper 추가
* 특징:
* - ship_data 테이블에서 IMO 번호 조회
* - IMO 번호를 100개씩 배치로 분할
* - Maritime API GetShipsByIHSLRorIMONumbers 호출
* TODO : GetShipsByIHSLRorIMONumbersAll 호출로 변경
* - Maritime API GetShipsByIHSLRorIMONumbersAll 호출
* - 선박 상세 정보를 ship_detail 테이블에 저장 (UPSERT)
*
* 데이터 흐름:
@ -41,12 +40,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; // ObjectMapper 추가
*/
/**
* 선박 상세 정보 Import Job Config
* I: ShipDetailComparisonData (Reader 출력)
* O: ShipDetailUpdate (Processor 출력)
* I: ShipDetailDto (Reader 출력)
* O: ShipDetailEntity (Processor 출력)
*/
@Slf4j
@Configuration
public class ShipDetailImportJobConfig extends BaseJobConfig<ShipDetailComparisonData, ShipDetailUpdate> {
public class ShipDetailImportJobConfig extends BaseJobConfig<ShipDetailDto, ShipDetailEntity> {
private final ShipDetailDataProcessor shipDetailDataProcessor;
private final ShipDetailDataWriter shipDetailDataWriter;
@ -81,18 +80,17 @@ public class ShipDetailImportJobConfig extends BaseJobConfig<ShipDetailCompariso
}
@Override
protected ItemReader<ShipDetailComparisonData> createReader() { // 타입 변경
// Reader 생성자 수정: ObjectMapper를 전달합니다.
protected ItemReader<ShipDetailDto> createReader() { // 타입 변경
return new ShipDetailDataReader(maritimeApiWebClient, jdbcTemplate, objectMapper);
}
@Override
protected ItemProcessor<ShipDetailComparisonData, ShipDetailUpdate> createProcessor() {
protected ItemProcessor<ShipDetailDto, ShipDetailEntity> createProcessor() {
return shipDetailDataProcessor;
}
@Override
protected ItemWriter<ShipDetailUpdate> createWriter() { // 타입 변경
protected ItemWriter<ShipDetailEntity> createWriter() { // 타입 변경
return shipDetailDataWriter;
}

파일 보기

@ -2,8 +2,8 @@ package com.snp.batch.jobs.shipdetail.batch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailComparisonData;
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailUpdate;
import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailDto;
import com.snp.batch.jobs.shipdetail.batch.entity.ShipDetailEntity;
import com.snp.batch.jobs.shipdetail.batch.processor.ShipDetailDataProcessor;
import com.snp.batch.jobs.shipdetail.batch.reader.ShipDetailUpdateDataReader;
import com.snp.batch.jobs.shipdetail.batch.writer.ShipDetailDataWriter;
@ -31,7 +31,7 @@ import org.springframework.web.reactive.function.client.WebClient;
@Slf4j
@Configuration
public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig<ShipDetailComparisonData, ShipDetailUpdate> {
public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig<ShipDetailDto, ShipDetailEntity> {
private final ShipDetailDataProcessor shipDetailDataProcessor;
private final ShipDetailDataWriter shipDetailDataWriter;
@ -46,7 +46,7 @@ public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig<ShipDetail
private String maritimeApiUrl;
protected String getApiKey() {return "SHIP_DETAIL_UPDATE_API";}
protected String getBatchUpdateSql() {
return String.format("UPDATE SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
return String.format("UPDATE T_SNP_DATA.BATCH_LAST_EXECUTION SET LAST_SUCCESS_DATE = NOW(), UPDATED_AT = NOW() WHERE API_KEY = '%s'", getApiKey());}
public ShipDetailUpdateJobConfig(
@ -101,17 +101,24 @@ public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig<ShipDetail
}
@Override
protected ItemReader<ShipDetailComparisonData> createReader() { // 타입 변경
protected ItemReader<ShipDetailDto> createReader() { // 타입 변경
return shipDetailUpdateDataReader;
}
@Override
protected ItemProcessor<ShipDetailComparisonData, ShipDetailUpdate> createProcessor() {
protected ItemProcessor<ShipDetailDto, ShipDetailEntity> createProcessor() {
return shipDetailDataProcessor;
}
@Bean
@StepScope
public ShipDetailDataProcessor shipDetailDataProcessor(
@Value("#{stepExecution.jobExecution.id}") Long jobExecutionId
) {
return new ShipDetailDataProcessor(jobExecutionId);
}
@Override
protected ItemWriter<ShipDetailUpdate> createWriter() { // 타입 변경
protected ItemWriter<ShipDetailEntity> createWriter() { // 타입 변경
return shipDetailDataWriter;
}

파일 보기

@ -2,6 +2,7 @@ package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.AdditionalInformationEntity;
import lombok.*;
@Getter
@ -44,4 +45,22 @@ public class AdditionalInformationDto {
private String satComID;
@JsonProperty("SatComAnsBack")
private String satComAnsBack;
public AdditionalInformationEntity toEntity() {
return AdditionalInformationEntity.builder()
.lrno(this.lrno)
.shipemail(this.shipEmail)
.waterdepthmax(this.waterDepthMax)
.drilldepthmax(this.drillDepthMax)
.drillbargeind(this.drillBargeInd)
.productionvesselind(this.productionVesselInd)
.deckheatexchangerind(this.deckHeatExchangerInd)
.deckheatexchangermaterial(this.deckHeatExchangerMaterial)
.tweendeckportable(this.tweenDeckPortable)
.tweendeckfixed(this.tweenDeckFixed)
.satcomid(this.satComID)
.satcomansback(this.satComAnsBack)
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getVersion() : null)
.build();
}
}

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.BareBoatCharterHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -27,4 +28,15 @@ public class BareBoatCharterHistoryDto {
private String bbChartererCode;
@JsonProperty("BBCharterer")
private String bbCharterer;
public BareBoatCharterHistoryEntity toEntity() {
return BareBoatCharterHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.sequence(this.sequence)
.effectiveDate(this.effectiveDate)
.bbChartererCode(this.bbChartererCode)
.bbCharterer(this.bbCharterer)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.CallSignAndMmsiHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -28,5 +29,15 @@ public class CallSignAndMmsiHistoryDto {
private String mmsi;
@JsonProperty("EffectiveDate")
private String effectiveDate;
// MMSI는 JSON에 없으므로 DTO에 포함하지 않음. Entity에서 처리.
public CallSignAndMmsiHistoryEntity toEntity() {
return CallSignAndMmsiHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.sequence(this.seqNo) // SeqNo -> sequence 매핑
.callsign(this.callSign)
.mmsi(this.mmsi) // DTO에 정의된 mmsi 필드 사용
.effectiveDate(this.effectiveDate)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.ClassHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -34,4 +35,18 @@ public class ClassHistoryDto {
private String lrno;
@JsonProperty("Sequence")
private String sequence;
public ClassHistoryEntity toEntity() {
return ClassHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
._class(this._class)
.classCode(this.classCode)
.classIndicator(this.classIndicator)
.classID(this.classID)
.currentIndicator(this.currentIndicator)
.effectiveDate(this.effectiveDate)
.lrno(this.lrno)
.sequence(this.sequence)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.CompanyDetailEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -79,4 +80,39 @@ public class CompanyDetailDto {
@JsonProperty("DataSetVersion")
private String dataSetVersion;
}
public CompanyDetailEntity toEntity() {
return CompanyDetailEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.owcode(this.owcode)
.shortcompanyname(this.shortCompanyName)
.countryname(this.countryName)
.townname(this.townName)
.telephone(this.telephone)
.telex(this.telex)
.emailaddress(this.emailaddress)
.website(this.website)
.fullname(this.fullName)
.careofcode(this.careOfCode)
.roomfloorbuilding1(this.roomFloorBuilding1)
.roomfloorbuilding2(this.roomFloorBuilding2)
.roomfloorbuilding3(this.roomFloorBuilding3)
.pobox(this.poBox)
.streetnumber(this.streetNumber)
.street(this.street)
.prepostcode(this.prePostcode)
.postpostcode(this.postPostcode)
.nationalityofregistration(this.nationalityofRegistration)
.nationalityofcontrol(this.nationalityofControl)
.locationcode(this.locationCode)
.nationalityofregistrationcode(this.nationalityofRegistrationCode)
.nationalityofcontrolcode(this.nationalityofControlCode)
.lastchangedate(this.lastChangeDate)
.parentcompany(this.parentCompany)
.companystatus(this.companyStatus)
.fulladdress(this.fullAddress)
.facsimile(this.facsimile)
.foundeddate(this.foundedDate)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.CompanyVesselRelationshipEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -61,4 +62,31 @@ public class CompanyVesselRelationshipDto {
private String technicalManagerGroup;
@JsonProperty("TechnicalManagerGroupCode")
private String technicalManagerGroupCode;
public CompanyVesselRelationshipEntity toEntity() {
return CompanyVesselRelationshipEntity.builder()
.datasetversion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.doccode(this.docCode)
.doccompany(this.docCompany)
.docgroup(this.docGroup)
.docgroupcode(this.docGroupCode)
.groupbeneficialowner(this.groupBeneficialOwner)
.groupbeneficialownercode(this.groupBeneficialOwnerCode)
.lrno(this.lrno)
.operator(this.operator)
.operatorcode(this.operatorCode)
.operatorgroup(this.operatorGroup)
.operatorgroupcode(this.operatorGroupCode)
.registeredowner(this.registeredOwner)
.registeredownercode(this.registeredOwnerCode)
.shipmanager(this.shipManager)
.shipmanagercode(this.shipManagerCode)
.shipmanagergroup(this.shipManagerGroup)
.shipmanagergroupcode(this.shipManagerGroupCode)
.technicalmanager(this.technicalManager)
.technicalmanagercode(this.technicalManagerCode)
.technicalmanagergroup(this.technicalManagerGroup)
.technicalmanagergroupcode(this.technicalManagerGroupCode)
.build();
}
}

파일 보기

@ -2,6 +2,7 @@ package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.CrewListEntity;
import lombok.*;
@Data
@ -58,4 +59,22 @@ public class CrewListDto {
@JsonProperty("TotalUndeclared")
private String totalUndeclared;
public CrewListEntity toEntity() {
return CrewListEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.id(this.id)
.lrno(this.lrno)
.shipname(this.shipname)
.crewlistdate(this.crewListDate)
.nationality(this.nationality)
.totalcrew(this.totalCrew)
.totalratings(this.totalRatings)
.totalofficers(this.totalOfficers)
.totalcadets(this.totalCadets)
.totaltrainees(this.totalTrainees)
.totalridingsquad(this.totalRidingSquad)
.totalundeclared(this.totalUndeclared)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.DarkActivityConfirmedEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -45,4 +46,36 @@ public class DarkActivityConfirmedDto {
@JsonProperty("Last_Port_of_Call") private String lastPortOfCall;
@JsonProperty("Last_Port_Country_Code") private String lastPortCountryCode;
@JsonProperty("Last_Port_Country") private String lastPortCountry;
public DarkActivityConfirmedEntity toEntity() {
return DarkActivityConfirmedEntity.builder()
.datasetversion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.mmsi(this.mmsi)
.vessel_name(this.vesselName)
.dark_hours(this.darkHours)
.dark_activity(this.darkActivity)
.dark_status(this.darkStatus)
.area_id(this.areaId)
.area_name(this.areaName)
.area_country(this.areaCountry)
.dark_time(this.darkTime)
.dark_latitude(this.darkLatitude)
.dark_longitude(this.darkLongitude)
.dark_speed(this.darkSpeed)
.dark_heading(this.darkHeading)
.dark_draught(this.darkDraught)
.nextseen(this.nextSeen)
.nextseen_latitude(this.nextSeenLatitude)
.nextseen_longitude(this.nextSeenLongitude)
.nextseen_speed(this.nextSeenSpeed)
.nextseen_draught(this.nextSeenDraught)
.nextseen_heading(this.nextSeenHeading)
.dark_reported_destination(this.darkReportedDestination)
.nextseen_reported_destination(this.nextSeenReportedDestination)
.last_port_of_call(this.lastPortOfCall)
.last_port_country_code(this.lastPortCountryCode)
.last_port_country(this.lastPortCountry)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.FlagHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -28,4 +29,15 @@ public class FlagHistoryDto {
private String lrno;
@JsonProperty("Sequence")
private String sequence;
public FlagHistoryEntity toEntity() {
return FlagHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.effectiveDate(this.effectiveDate)
.flag(this.flag)
.flagCode(this.flagCode)
.lrno(this.lrno)
.sequence(this.sequence)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.GroupBeneficialOwnerHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -12,7 +13,6 @@ import lombok.ToString;
@NoArgsConstructor
public class GroupBeneficialOwnerHistoryDto {
// Nested class for DataSetVersion object
@Getter
@Setter
@ToString
@ -42,4 +42,16 @@ public class GroupBeneficialOwnerHistoryDto {
@JsonProperty("Sequence")
private String sequence; // 순번
public GroupBeneficialOwnerHistoryEntity toEntity() {
return GroupBeneficialOwnerHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.companyStatus(this.companyStatus)
.effectiveDate(this.effectiveDate)
.groupBeneficialOwner(this.groupBeneficialOwner)
.groupBeneficialOwnerCode(this.groupBeneficialOwnerCode)
.lrno(this.lrno)
.sequence(this.sequence)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.IceClassEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -24,4 +25,13 @@ public class IceClassDto {
private String iceClassCode;
@JsonProperty("LRNO")
private String lrno;
public IceClassEntity toEntity() {
return IceClassEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.iceClass(this.iceClass)
.iceClassCode(this.iceClassCode)
.lrno(this.lrno)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.NameHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -26,4 +27,14 @@ public class NameHistoryDto {
private String sequence;
@JsonProperty("VesselName")
private String vesselName;
public NameHistoryEntity toEntity() {
return NameHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.effectiveDate(this.effectiveDate)
.lrno(this.lrno)
.sequence(this.sequence)
.vesselName(this.vesselName)
.build();
}
}

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.OperatorHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -40,4 +41,16 @@ public class OperatorHistoryDto {
@JsonProperty("Sequence")
private String sequence;
public OperatorHistoryEntity toEntity() {
return OperatorHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.companyStatus(this.companyStatus)
.effectiveDate(this.effectiveDate)
.lrno(this.lrno)
.operator(this.operator)
.operatorCode(this.operatorCode)
.sequence(this.sequence)
.build();
}
}

파일 보기

@ -2,6 +2,7 @@ package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.OwnerHistoryEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -61,4 +62,16 @@ public class OwnerHistoryDto {
@JsonProperty("DataSetVersion")
private String version;
}
public OwnerHistoryEntity toEntity(){
return OwnerHistoryEntity.builder()
.CompanyStatus(this.CompanyStatus)
.EffectiveDate(this.EffectiveDate)
.LRNO(this.LRNO)
.Owner(this.Owner)
.OwnerCode(this.OwnerCode)
.Sequence(this.Sequence)
.dataSetVersion(this.dataSetVersion.version)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.PandIHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -30,4 +31,16 @@ public class PandIHistoryDto {
private String effectiveDate;
@JsonProperty("Source")
private String source;
public PandIHistoryEntity toEntity() {
return PandIHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.sequence(this.sequence)
.pandiclubcode(this.pandIClubCode)
.pandiclubdecode(this.pandIClubDecode)
.effectiveDate(this.effectiveDate)
.source(this.source)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.SafetyManagementCertificateHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -46,4 +47,24 @@ public class SafetyManagementCertificateHistoryDto {
private String safetyManagementCertificateCompanyCode;
@JsonProperty("Sequence")
private String sequence;
public SafetyManagementCertificateHistoryEntity toEntity() {
return SafetyManagementCertificateHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.safetyManagementCertificateAuditor(this.safetyManagementCertificateAuditor)
.safetyManagementCertificateConventionOrVol(this.safetyManagementCertificateConventionOrVol)
.safetyManagementCertificateDateExpires(this.safetyManagementCertificateDateExpires)
.safetyManagementCertificateDateIssued(this.safetyManagementCertificateDateIssued)
.safetyManagementCertificateDOCCompany(this.safetyManagementCertificateDOCCompany)
.safetyManagementCertificateFlag(this.safetyManagementCertificateFlag)
.safetyManagementCertificateIssuer(this.safetyManagementCertificateIssuer)
.safetyManagementCertificateOtherDescription(this.safetyManagementCertificateOtherDescription)
.safetyManagementCertificateShipName(this.safetyManagementCertificateShipName)
.safetyManagementCertificateShipType(this.safetyManagementCertificateShipType)
.safetyManagementCertificateSource(this.safetyManagementCertificateSource)
.safetyManagementCertificateCompanyCode(this.safetyManagementCertificateCompanyCode)
.sequence(this.sequence)
.build();
}
}

파일 보기

@ -476,7 +476,7 @@ public class ShipDetailDto {
* API: CompanyVesselRelationships
*/
@JsonProperty("CompanyVesselRelationships")
private List<CompanyVesselRelationshipDto> CompanyVesselRelationships;
private List<CompanyVesselRelationshipDto> companyVesselRelationships;
/**
* 다크활동이력 정보 List
@ -486,6 +486,6 @@ public class ShipDetailDto {
private List<DarkActivityConfirmedDto> darkActivityConfirmed;
@JsonProperty("CompanyDetailsComplexWithCodesAndParent")
private List<CompanyDetailDto> companyDetailDtoList;
private List<CompanyDetailDto> companyDetail;
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.ShipManagerHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -42,4 +43,16 @@ public class ShipManagerHistoryDto {
@JsonProperty("ShipManagerCode")
private String shipManagerCode;
public ShipManagerHistoryEntity toEntity() {
return ShipManagerHistoryEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.companyStatus(this.companyStatus)
.effectiveDate(this.effectiveDate)
.lrno(this.lrno)
.sequence(this.sequence)
.shipManager(this.shipManager)
.shipManagerCode(this.shipManagerCode)
.build();
}
}

파일 보기

@ -19,8 +19,7 @@ public class ShipResultDto {
private Integer shipCount;
@JsonProperty("APSShipDetail")
private JsonNode shipDetailNode;
// Getter and Setter
public JsonNode getShipDetailNode() { return shipDetailNode; }
private ShipDetailDto shipDetails;
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.SisterShipLinksEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -22,4 +23,12 @@ public class SisterShipLinksDto {
private String lrno;
@JsonProperty("LinkedLRNO")
private String linkedLRNO;
public SisterShipLinksEntity toEntity() {
return SisterShipLinksEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.linkedLRNO(this.linkedLRNO)
.build();
}
}

파일 보기

@ -1,6 +1,7 @@
package com.snp.batch.jobs.shipdetail.batch.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.snp.batch.jobs.shipdetail.batch.entity.SpecialFeatureEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -26,4 +27,14 @@ public class SpecialFeatureDto {
private String specialFeature;
@JsonProperty("SpecialFeatureCode")
private String specialFeatureCode;
public SpecialFeatureEntity toEntity() {
return SpecialFeatureEntity.builder()
.dataSetVersion(this.dataSetVersion != null ? this.dataSetVersion.getDataSetVersion() : null)
.lrno(this.lrno)
.sequence(this.sequence)
.specialFeature(this.specialFeature)
.specialFeatureCode(this.specialFeatureCode)
.build();
}
}

Some files were not shown because too many files have changed in this diff Show More