startDate, endDate로직처리

This commit is contained in:
Kim JiMyeung 2025-12-22 13:11:25 +09:00
부모 e7ea47b02c
커밋 75531ab5e5
7개의 변경된 파일83개의 추가작업 그리고 24개의 파일을 삭제

파일 보기

@ -6,6 +6,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@ -16,7 +18,7 @@ public class EventDetailDto {
@JsonProperty("IncidentID")
private Integer incidentID;
@JsonProperty("EventID")
private Integer eventID;
private Long eventID;
@JsonProperty("EventTypeID")
private Integer eventTypeID;
@JsonProperty("EventType")
@ -93,6 +95,8 @@ public class EventDetailDto {
private String component2;
@JsonProperty("FiredUpon")
private String firedUpon;
private String eventStartDate;
private String eventEndDate;
@JsonProperty("Cargoes")
private List<CargoDto> cargoes;

파일 보기

@ -0,0 +1,12 @@
package com.snp.batch.jobs.event.batch.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
public class EventPeriod {
private String eventStartDate;
private String eventEndDate;}

파일 보기

@ -1,5 +1,6 @@
package com.snp.batch.jobs.event.batch.entity;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -7,6 +8,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.time.LocalDateTime;
import java.util.List;
@Data
@ -16,7 +18,7 @@ import java.util.List;
@EqualsAndHashCode(callSuper = true)
public class EventDetailEntity extends BaseEntity {
private Integer incidentID;
private Integer eventID;
private Long eventID;
private Integer eventTypeID;
private String eventType;
private String significance;
@ -56,6 +58,9 @@ public class EventDetailEntity extends BaseEntity {
private String component2;
private String firedUpon;
private String eventStartDate;
private String eventEndDate;
private List<CargoEntity> cargoes;
private List<HumanCasualtyEntity> humanCasualties;
private List<RelationshipEntity> relationships;

파일 보기

@ -19,8 +19,8 @@ public class EventDataProcessor extends BaseProcessor<EventDetailDto, EventDetai
log.debug("Event 데이터 처리 시작: Event ID = {}", dto.getEventID());
EventDetailEntity entity = EventDetailEntity.builder()
.incidentID(dto.getIncidentID())
.eventID(dto.getEventID())
.incidentID(dto.getIncidentID())
.eventTypeID(dto.getEventTypeID())
.eventType(dto.getEventType())
.significance(dto.getSignificance())
@ -59,6 +59,8 @@ public class EventDataProcessor extends BaseProcessor<EventDetailDto, EventDetai
.publishedDate(dto.getPublishedDate())
.component2(dto.getComponent2())
.firedUpon(dto.getFiredUpon())
.eventStartDate(dto.getEventStartDate())
.eventEndDate(dto.getEventEndDate())
.cargoes(dto.getCargoes() != null ?
dto.getCargoes().stream().map(CargoDto::toEntity).collect(Collectors.toList()) : null)
.humanCasualties(dto.getHumanCasualties() != null ?

파일 보기

@ -11,14 +11,14 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class EventDataReader extends BaseApiReader<EventDetailDto> {
private Map<Long, EventPeriod> eventPeriodMap;
private final JdbcTemplate jdbcTemplate;
private final BatchDateService batchDateService; // BatchDateService 필드 추가
@ -39,10 +39,13 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
return "/MaritimeWCF/MaritimeAndTradeEventsService.svc/RESTFul/GetEventListByEventChangeDateRange";
}
protected String getEventDetailApiPath(){
protected String getEventDetailApiPath() {
return "/MaritimeWCF/MaritimeAndTradeEventsService.svc/RESTFul/GetEventDataByEventID";
}
protected String getApiKey() {return "EVENT_IMPORT_JOB";}
protected String getApiKey() {
return "EVENT_IMPORT_JOB";
}
// 배치 처리 상태
private List<Long> eventIds;
@ -54,9 +57,11 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
protected void resetCustomState() {
this.currentBatchIndex = 0;
this.eventIds = null;
this.eventPeriodMap = new HashMap<>();
}
@Override
protected void beforeFetch(){
protected void beforeFetch() {
// 1. 기간내 기록된 Event List 조회 (API 요청)
log.info("Event API 호출");
EventResponse response = callEventApiWithBatch();
@ -65,8 +70,19 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
eventIds = extractEventIdList(response);
log.info("EvnetId List 추출 완료 : {} 개", eventIds.size());
eventPeriodMap = response.getMaritimeEvents().stream()
.filter(e -> e.getEventId() != null)
.collect(Collectors.toMap(
EventDto::getEventId,
e -> new EventPeriod(
e.getStartDate(),
e.getEndDate()
)
));
updateApiCallStats(eventIds.size(), 0);
}
@Override
protected List<EventDetailDto> fetchNextBatch() throws Exception {
// 3. EventID List Event Detail 조회 (API요청) : 청크단위 실행
@ -95,12 +111,21 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
currentBatchIndex = endIndex;
List<EventDetailDto> eventDetailList = new ArrayList<>();
// TODO: getEventDetailDto에 Map<EventId,Map<StartDate,EndDate>> 데이터 세팅
eventDetailList.add(response.getEventDetailDto());
// 응답 처리
if (response != null && response.getEventDetailDto() != null) {
// TODO: getEventDetailDto에 Map<EventId,Map<StartDate,EndDate>> 데이터 세팅
EventDetailDto detailDto = response.getEventDetailDto();
Long eventId = detailDto.getEventID();
EventPeriod period = eventPeriodMap.get(eventId);
if (period != null) {
detailDto.setEventStartDate(period.getEventStartDate());
detailDto.setEventEndDate(period.getEventEndDate());
}
eventDetailList.add(response.getEventDetailDto());
log.info("[{}] 배치 {}/{} 완료: {} 건 조회",
getReaderName(), currentBatchNumber, totalBatches, eventDetailList.size());
@ -141,7 +166,7 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
@Override
protected void afterFetch(List<EventDetailDto> data) {
int totalBatches = (int) Math.ceil((double) eventIds.size() / batchSize);
try{
try {
if (data == null) {
// 3. 배치 성공 상태 업데이트 (트랜잭션 커밋 직전에 실행)
LocalDate successDate = LocalDate.now(); // 현재 배치 실행 시점의 날짜 (Reader의 toDay와 동일한 )
@ -152,7 +177,7 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
log.info("[{}] 총 {} 개의 Event ID에 대한 API 호출 종료",
getReaderName(), eventIds.size());
}
}catch (Exception e){
} catch (Exception e) {
log.info("[{}] 전체 {} 개 배치 처리 실패", getReaderName(), totalBatches);
log.info("[{}] 총 {} 개의 Event ID에 대한 API 호출 종료",
getReaderName(), eventIds.size());
@ -163,7 +188,7 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
if (response.getMaritimeEvents() == null) {
return Collections.emptyList();
}
return response.getMaritimeEvents() .stream()
return response.getMaritimeEvents().stream()
// ShipDto 객체에서 imoNumber 필드 (String 타입) 추출
.map(EventDto::getEventId)
// IMO 번호가 null이 아닌 경우만 필터링 (선택 사항이지만 안전성을 위해)
@ -207,4 +232,11 @@ public class EventDataReader extends BaseApiReader<EventDetailDto> {
.block();
}
private LocalDateTime parseToLocalDate(String value) {
if (value == null || value.isBlank()) {
return null;
}
return LocalDateTime.parse(value);
}
}

파일 보기

@ -162,14 +162,16 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setObject(idx++, entity.getIncidentID()); // incident_id (누락됨)
ps.setObject(idx++, entity.getIhslrOrImoShipNo()); // ihslrorimoshipno (누락됨)
ps.setObject(idx++, entity.getPublishedDate()); // published_date (누락됨)
ps.setObject(idx++, entity.getEventStartDate()); // event_start_date
ps.setObject(idx++, entity.getEventEndDate()); // event_end_date
ps.setString(idx++, entity.getAttemptedBoarding()); // attempted_boarding
ps.setString(idx++, entity.getCargoLoadingStatusCode());// cargo_loading_status_code
ps.setString(idx++, entity.getCasualtyAction()); // casualty_action
ps.setString(idx++, entity.getCasualtyZone()); // casualty_zone
ps.setString(idx++, entity.getCasualtyZoneCode()); // casualty_zone_code
ps.setString(idx++, entity.getComponent2()); // component2
// 11~20
ps.setString(idx++, entity.getCasualtyZoneCode()); // casualty_zone_code
ps.setString(idx++, entity.getComponent2()); // component2
ps.setString(idx++, entity.getCountryCode()); // country_code
ps.setObject(idx++, entity.getDateOfBuild()); // date_of_build (Integer)
ps.setString(idx++, entity.getDescription()); // description
@ -178,10 +180,10 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setObject(idx++, entity.getMarsdenGridReference()); // marsden_grid_reference (Integer)
ps.setString(idx++, entity.getTownName()); // town_name
ps.setString(idx++, entity.getEventType()); // event_type (누락됨)
ps.setString(idx++, entity.getEventTypeDetail()); // event_type_detail
ps.setObject(idx++, entity.getEventTypeDetailID()); // event_type_detail_id (Integer)
// 21~30
ps.setString(idx++, entity.getEventTypeDetail()); // event_type_detail
ps.setObject(idx++, entity.getEventTypeDetailID()); // event_type_detail_id (Integer)
ps.setObject(idx++, entity.getEventTypeID()); // event_type_id (Integer)
ps.setString(idx++, entity.getFiredUpon()); // fired_upon
ps.setString(idx++, entity.getHeadline()); // headline (누락됨)
@ -190,10 +192,10 @@ public class EventRepositoryImpl extends BaseJdbcRepository<EventDetailEntity, L
ps.setString(idx++, entity.getWeather()); // weather
ps.setString(idx++, entity.getPollutant()); // pollutant
ps.setObject(idx++, entity.getPollutantQuantity()); // pollutant_quantity (Double)
// 31~42
ps.setString(idx++, entity.getPollutantUnit()); // pollutant_unit
ps.setString(idx++, entity.getRegisteredOwnerCodeAtTime()); // registered_owner_code_at_time
// 31~40
ps.setString(idx++, entity.getRegisteredOwnerAtTime()); // registered_owner_at_time
ps.setString(idx++, entity.getRegisteredOwnerCountryCodeAtTime()); // registered_owner_country_code_at_time
ps.setString(idx++, entity.getRegisteredOwnerCountryAtTime()); // registered_owner_country_at_time

파일 보기

@ -4,7 +4,7 @@ public class EventSql {
public static String getEventDetailUpdateSql(){
return """
INSERT INTO snp_data.event_detail (
event_id, incident_id, ihslrorimoshipno, published_date,
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,
date_of_build, description, environment_location, location_name,
@ -17,7 +17,7 @@ public class EventSql {
vessel_name, vessel_type, vessel_type_decode
)
VALUES (
?, ?, ?, ?::timestamptz, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?::timestamptz,?::timestamptz,?::timestamptz, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?
@ -27,6 +27,8 @@ public class EventSql {
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,