✨ S&P 국가코드,선박유형코드 Import Job
This commit is contained in:
부모
fb10e3cc39
커밋
084be88b98
@ -0,0 +1,102 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.config;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.config.BaseJobConfig;
|
||||||
|
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.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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.batch.core.Job;
|
||||||
|
import org.springframework.batch.core.Step;
|
||||||
|
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;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ship Data Import Job 설정
|
||||||
|
* BaseJobConfig를 상속하여 구현
|
||||||
|
*
|
||||||
|
* Maritime API에서 선박 데이터를 받아 PostgreSQL에 저장하는 배치 작업:
|
||||||
|
* - Maritime API에서 170,000+ 선박 IMO 번호 조회
|
||||||
|
* - 중복 체크 및 업데이트 로직
|
||||||
|
* - PostgreSQL에 저장
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class FlagCodeImportJobConfig extends BaseJobConfig<FlagCodeDto, FlagCodeEntity> {
|
||||||
|
|
||||||
|
private final FlagCodeRepository flagCodeRepository;
|
||||||
|
private final WebClient maritimeApiWebClient;
|
||||||
|
|
||||||
|
@Value("${app.batch.chunk-size:1000}")
|
||||||
|
private int chunkSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 생성자 주입
|
||||||
|
* maritimeApiWebClient: MaritimeApiWebClientConfig에서 등록한 Bean 주입
|
||||||
|
*/
|
||||||
|
public FlagCodeImportJobConfig(
|
||||||
|
JobRepository jobRepository,
|
||||||
|
PlatformTransactionManager transactionManager,
|
||||||
|
FlagCodeRepository flagCodeRepository,
|
||||||
|
@Qualifier("maritimeApiWebClient") WebClient maritimeApiWebClient) {
|
||||||
|
super(jobRepository, transactionManager);
|
||||||
|
this.flagCodeRepository = flagCodeRepository;
|
||||||
|
this.maritimeApiWebClient = maritimeApiWebClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getJobName() {
|
||||||
|
return "FlagCodeImportJob";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getStepName() {
|
||||||
|
return "FlagCodeImportStep";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemReader<FlagCodeDto> createReader() {
|
||||||
|
return new FlagCodeDataReader(maritimeApiWebClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemProcessor<FlagCodeDto, FlagCodeEntity> createProcessor() {
|
||||||
|
return new FlagCodeDataProcessor(flagCodeRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemWriter<FlagCodeEntity> createWriter() {
|
||||||
|
return new FlagCodeDataWriter(flagCodeRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getChunkSize() {
|
||||||
|
return chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job Bean 등록
|
||||||
|
*/
|
||||||
|
@Bean(name = "FlagCodeImportJob")
|
||||||
|
public Job flagCodeImportJob() {
|
||||||
|
return job();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step Bean 등록
|
||||||
|
*/
|
||||||
|
@Bean(name = "FlagCodeImportStep")
|
||||||
|
public Step flagCodeImportStep() {
|
||||||
|
return step();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.config;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.config.BaseJobConfig;
|
||||||
|
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.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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.batch.core.Job;
|
||||||
|
import org.springframework.batch.core.Step;
|
||||||
|
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.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class Stat5CodeImportJobConfig extends BaseJobConfig<Stat5CodeDto, Stat5CodeEntity> {
|
||||||
|
|
||||||
|
private final Stat5CodeRepository stat5CodeRepository;
|
||||||
|
private final WebClient maritimeAisApiWebClient;
|
||||||
|
public Stat5CodeImportJobConfig(
|
||||||
|
JobRepository jobRepository,
|
||||||
|
PlatformTransactionManager transactionManager,
|
||||||
|
Stat5CodeRepository stat5CodeRepository,
|
||||||
|
@Qualifier("maritimeAisApiWebClient") WebClient maritimeAisApiWebClient) {
|
||||||
|
super(jobRepository, transactionManager);
|
||||||
|
this.stat5CodeRepository = stat5CodeRepository;
|
||||||
|
this.maritimeAisApiWebClient = maritimeAisApiWebClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getJobName() { return "Stat5CodeImportJob"; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getStepName() {
|
||||||
|
return "Stat5CodeImportStep";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemReader<Stat5CodeDto> createReader() { return new Stat5CodeDataReader(maritimeAisApiWebClient); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemProcessor<Stat5CodeDto, Stat5CodeEntity> createProcessor() { return new Stat5CodeDataProcessor(stat5CodeRepository); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ItemWriter<Stat5CodeEntity> createWriter() { return new Stat5CodeDataWriter(stat5CodeRepository); }
|
||||||
|
|
||||||
|
@Bean(name = "Stat5CodeImportJob")
|
||||||
|
public Job stat5CodeImportJob() {
|
||||||
|
return job();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step Bean 등록
|
||||||
|
*/
|
||||||
|
@Bean(name = "Stat5CodeImportStep")
|
||||||
|
public Step stat5CodeImportStep() {
|
||||||
|
return step();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class FlagCodeApiResponse {
|
||||||
|
|
||||||
|
@JsonProperty("associatedName")
|
||||||
|
private String associatedName;
|
||||||
|
|
||||||
|
@JsonProperty("associatedCount")
|
||||||
|
private Integer associatedCount;
|
||||||
|
|
||||||
|
@JsonProperty("APSAssociatedFlagISODetails")
|
||||||
|
private List<FlagCodeDto> associatedFlagISODetails;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class FlagCodeDto {
|
||||||
|
|
||||||
|
@JsonProperty("DataSetVersion")
|
||||||
|
private DataSetVersion dataSetVersion;
|
||||||
|
|
||||||
|
@JsonProperty("Code")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@JsonProperty("Decode")
|
||||||
|
private String decode;
|
||||||
|
|
||||||
|
@JsonProperty("ISO2")
|
||||||
|
private String iso2;
|
||||||
|
|
||||||
|
@JsonProperty("ISO3")
|
||||||
|
private String iso3;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class DataSetVersion {
|
||||||
|
@JsonProperty("DataSetVersion")
|
||||||
|
private String version;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class Stat5CodeApiResponse {
|
||||||
|
@JsonProperty("StatcodeArr")
|
||||||
|
private List<Stat5CodeDto> statcodeArr;
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class Stat5CodeDto {
|
||||||
|
@JsonProperty("Level1")
|
||||||
|
private String level1;
|
||||||
|
@JsonProperty("Level1Decode")
|
||||||
|
private String Level1Decode;
|
||||||
|
@JsonProperty("Level2")
|
||||||
|
private String Level2;
|
||||||
|
@JsonProperty("Level2Decode")
|
||||||
|
private String Level2Decode;
|
||||||
|
@JsonProperty("Level3")
|
||||||
|
private String Level3;
|
||||||
|
@JsonProperty("Level3Decode")
|
||||||
|
private String Level3Decode;
|
||||||
|
@JsonProperty("Level4")
|
||||||
|
private String Level4;
|
||||||
|
@JsonProperty("Level4Decode")
|
||||||
|
private String Level4Decode;
|
||||||
|
@JsonProperty("Level5")
|
||||||
|
private String Level5;
|
||||||
|
@JsonProperty("Level5Decode")
|
||||||
|
private String Level5Decode;
|
||||||
|
@JsonProperty("Description")
|
||||||
|
private String Description;
|
||||||
|
@JsonProperty("Release")
|
||||||
|
private Integer Release;
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.snp.batch.jobs.common.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 선박 엔티티 - JDBC 전용
|
||||||
|
* Maritime API 데이터 저장
|
||||||
|
*
|
||||||
|
* 테이블: ship_data
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class FlagCodeEntity extends BaseEntity {
|
||||||
|
|
||||||
|
private String dataSetVersion;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String decode;
|
||||||
|
|
||||||
|
private String iso2;
|
||||||
|
|
||||||
|
private String iso3;
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.snp.batch.common.batch.entity.BaseEntity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Stat5CodeEntity extends BaseEntity {
|
||||||
|
|
||||||
|
private String level1;
|
||||||
|
|
||||||
|
private String Level1Decode;
|
||||||
|
|
||||||
|
private String Level2;
|
||||||
|
|
||||||
|
private String Level2Decode;
|
||||||
|
|
||||||
|
private String Level3;
|
||||||
|
|
||||||
|
private String Level3Decode;
|
||||||
|
|
||||||
|
private String Level4;
|
||||||
|
|
||||||
|
private String Level4Decode;
|
||||||
|
|
||||||
|
private String Level5;
|
||||||
|
|
||||||
|
private String Level5Decode;
|
||||||
|
|
||||||
|
private String Description;
|
||||||
|
|
||||||
|
private String Release;
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShipDto를 ShipEntity로 변환하는 Processor
|
||||||
|
* BaseProcessor를 상속하여 공통 변환 패턴 적용
|
||||||
|
* 중복 체크 및 업데이트 로직 포함
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FlagCodeDataProcessor extends BaseProcessor<FlagCodeDto, FlagCodeEntity> {
|
||||||
|
|
||||||
|
private final FlagCodeRepository commonCodeRepository;
|
||||||
|
|
||||||
|
public FlagCodeDataProcessor(FlagCodeRepository commonCodeRepository) {
|
||||||
|
this.commonCodeRepository = commonCodeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FlagCodeEntity processItem(FlagCodeDto dto) throws Exception {
|
||||||
|
|
||||||
|
FlagCodeEntity entity = FlagCodeEntity.builder()
|
||||||
|
.dataSetVersion(dto.getDataSetVersion().getVersion())
|
||||||
|
.code(dto.getCode())
|
||||||
|
.decode(dto.getDecode())
|
||||||
|
.iso2(dto.getIso2())
|
||||||
|
.iso3(dto.getIso3())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.debug("국가코드 데이터 처리 완료: FlagCode={}", dto.getCode());
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
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 java.sql.PreparedStatement;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class Stat5CodeDataProcessor extends BaseProcessor<Stat5CodeDto, Stat5CodeEntity> {
|
||||||
|
private final Stat5CodeRepository stat5CodeRepository;
|
||||||
|
|
||||||
|
public Stat5CodeDataProcessor(Stat5CodeRepository stat5CodeRepository) {
|
||||||
|
this.stat5CodeRepository = stat5CodeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stat5CodeEntity processItem(Stat5CodeDto dto) throws Exception {
|
||||||
|
Stat5CodeEntity entity = Stat5CodeEntity.builder()
|
||||||
|
.level1(dto.getLevel1())
|
||||||
|
.Level1Decode(dto.getLevel1Decode())
|
||||||
|
.Level2(dto.getLevel2())
|
||||||
|
.Level2Decode(dto.getLevel2Decode())
|
||||||
|
.Level3(dto.getLevel3())
|
||||||
|
.Level3Decode(dto.getLevel3Decode())
|
||||||
|
.Level4(dto.getLevel4())
|
||||||
|
.Level4Decode(dto.getLevel4Decode())
|
||||||
|
.Level5(dto.getLevel5())
|
||||||
|
.Level5Decode(dto.getLevel5Decode())
|
||||||
|
.Description(dto.getDescription())
|
||||||
|
.Release(Integer.toString(dto.getRelease()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.debug("Stat5Code 데이터 처리 완료: Stat5Code={}", dto.getLevel5());
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maritime API에서 선박 데이터를 읽어오는 ItemReader
|
||||||
|
* BaseApiReader v2.0을 상속하여 공통 API 호출 패턴 적용
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FlagCodeDataReader extends BaseApiReader<FlagCodeDto> {
|
||||||
|
|
||||||
|
public FlagCodeDataReader(WebClient webClient) {
|
||||||
|
super(webClient); // BaseApiReader에 WebClient 전달
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 필수 구현 메서드
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getReaderName() {
|
||||||
|
return "FlagCodeDataReader";
|
||||||
|
}
|
||||||
|
|
||||||
|
@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<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("GetAssociatedFlagISOByName API 호출 실패", e);
|
||||||
|
log.error("에러 메시지: {}", e.getMessage());
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class Stat5CodeDataReader extends BaseApiReader<Stat5CodeDto> {
|
||||||
|
public Stat5CodeDataReader(WebClient webClient) {
|
||||||
|
super(webClient); // BaseApiReader에 WebClient 전달
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected String getReaderName() {
|
||||||
|
return "Stat5CodeDataReader";
|
||||||
|
}
|
||||||
|
@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<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("GetAssociatedFlagISOByName API 호출 실패", e);
|
||||||
|
log.error("에러 메시지: {}", e.getMessage());
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.repository;
|
||||||
|
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShipEntity Repository 인터페이스
|
||||||
|
* 구현체: ShipRepositoryImpl (JdbcTemplate 기반)
|
||||||
|
*/
|
||||||
|
public interface FlagCodeRepository {
|
||||||
|
|
||||||
|
void saveAllFlagCode(List<FlagCodeEntity> items);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.repository;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShipEntity Repository (JdbcTemplate 기반)
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Repository("FlagCodeRepository")
|
||||||
|
public class FlagCodeRepositoryImpl extends BaseJdbcRepository<FlagCodeEntity, String> implements FlagCodeRepository {
|
||||||
|
|
||||||
|
public FlagCodeRepositoryImpl(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEntityName() {
|
||||||
|
return "FlagCodeEntity";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTableName() {
|
||||||
|
return "snp_data.flagcode";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getInsertSql() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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'
|
||||||
|
""";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setInsertParameters(PreparedStatement ps, FlagCodeEntity entity) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUpdateParameters(PreparedStatement ps, FlagCodeEntity entity) throws Exception {
|
||||||
|
int idx = 1;
|
||||||
|
ps.setString(idx++, entity.getDataSetVersion());
|
||||||
|
ps.setString(idx++, entity.getCode());
|
||||||
|
ps.setString(idx++, entity.getDecode());
|
||||||
|
ps.setString(idx++, entity.getIso2());
|
||||||
|
ps.setString(idx++, entity.getIso3());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RowMapper<FlagCodeEntity> getRowMapper() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String extractId(FlagCodeEntity entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveAllFlagCode(List<FlagCodeEntity> items) {
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jdbcTemplate.batchUpdate(getUpdateSql(), items, items.size(),
|
||||||
|
(ps, entity) -> {
|
||||||
|
try {
|
||||||
|
setUpdateParameters(ps, entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("배치 삽입 파라미터 설정 실패", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("{} 전체 저장 완료: {} 건", getEntityName(), items.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.repository;
|
||||||
|
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Stat5CodeRepository {
|
||||||
|
void saveAllStat5Code(List<Stat5CodeEntity> items);
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.repository;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Repository("Stat5CodeRepository")
|
||||||
|
public class Stat5CodeRepositoryImpl extends BaseJdbcRepository<Stat5CodeEntity, String> implements Stat5CodeRepository{
|
||||||
|
public Stat5CodeRepositoryImpl(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEntityName() {
|
||||||
|
return "Stat5CodeEntity";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTableName() {
|
||||||
|
return "snp_data.stat5code";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RowMapper<Stat5CodeEntity> getRowMapper() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String extractId(Stat5CodeEntity entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getInsertSql() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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'
|
||||||
|
""";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setInsertParameters(PreparedStatement ps, Stat5CodeEntity entity) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUpdateParameters(PreparedStatement ps, Stat5CodeEntity entity) throws Exception {
|
||||||
|
int idx = 1;
|
||||||
|
ps.setString(idx++, entity.getLevel1());
|
||||||
|
ps.setString(idx++, entity.getLevel1Decode());
|
||||||
|
ps.setString(idx++, entity.getLevel2());
|
||||||
|
ps.setString(idx++, entity.getLevel2Decode());
|
||||||
|
ps.setString(idx++, entity.getLevel3());
|
||||||
|
ps.setString(idx++, entity.getLevel3Decode());
|
||||||
|
ps.setString(idx++, entity.getLevel4());
|
||||||
|
ps.setString(idx++, entity.getLevel4Decode());
|
||||||
|
ps.setString(idx++, entity.getLevel5());
|
||||||
|
ps.setString(idx++, entity.getLevel5Decode());
|
||||||
|
ps.setString(idx++, entity.getDescription());
|
||||||
|
ps.setString(idx++, entity.getRelease());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveAllStat5Code(List<Stat5CodeEntity> items) {
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jdbcTemplate.batchUpdate(getUpdateSql(), items, items.size(),
|
||||||
|
(ps, entity) -> {
|
||||||
|
try {
|
||||||
|
setUpdateParameters(ps, entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("배치 삽입 파라미터 설정 실패", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("{} 전체 저장 완료: {} 건", getEntityName(), items.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.writer;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.writer.BaseWriter;
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
|
||||||
|
import com.snp.batch.jobs.common.batch.repository.FlagCodeRepository;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShipEntity를 DB에 저장하는 ItemWriter
|
||||||
|
* BaseWriter를 상속하여 공통 저장 패턴 적용
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FlagCodeDataWriter extends BaseWriter<FlagCodeEntity> {
|
||||||
|
|
||||||
|
private final FlagCodeRepository flagCodeRepository;
|
||||||
|
|
||||||
|
public FlagCodeDataWriter(FlagCodeRepository flagCodeRepository) {
|
||||||
|
super("FlagCodeEntity");
|
||||||
|
this.flagCodeRepository = flagCodeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeItems(List<FlagCodeEntity> items) throws Exception {
|
||||||
|
flagCodeRepository.saveAllFlagCode(items);
|
||||||
|
log.info("FlagCode 저장 완료: {} 건", items.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.snp.batch.jobs.common.batch.writer;
|
||||||
|
|
||||||
|
import com.snp.batch.common.batch.writer.BaseWriter;
|
||||||
|
import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
|
||||||
|
import com.snp.batch.jobs.common.batch.repository.Stat5CodeRepository;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class Stat5CodeDataWriter extends BaseWriter<Stat5CodeEntity> {
|
||||||
|
|
||||||
|
private final Stat5CodeRepository stat5CodeRepository;
|
||||||
|
|
||||||
|
public Stat5CodeDataWriter(Stat5CodeRepository stat5CodeRepository) {
|
||||||
|
super("Stat5CodeEntity");
|
||||||
|
this.stat5CodeRepository = stat5CodeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeItems(List<Stat5CodeEntity> items) throws Exception {
|
||||||
|
stat5CodeRepository.saveAllStat5Code(items);
|
||||||
|
log.info("Stat5Code 저장 완료: {} 건", items.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
불러오는 중...
Reference in New Issue
Block a user