S&P 국가코드,선박유형코드 Import Job

This commit is contained in:
hyojin kim 2025-12-16 14:12:22 +09:00
부모 fb10e3cc39
커밋 084be88b98
18개의 변경된 파일839개의 추가작업 그리고 0개의 파일을 삭제

파일 보기

@ -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());
}
}