MultiType Write
-
배치 작업 Xml Sample
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd">
<!--
* 배치작업 : DB TO MULTI TYPE(ITEM) 파일 샘플
* 배치스텝
- sample-db-to-multi-item-001 : DB TO FIXED MULTI TYPE 파일 처리
- sample-db-to-multi-item-002 : DB TO DELIMITED MULTI TYPE 파일 처리
-->
<job id="sample-db-to-multi-item" xmlns="http://www.springframework.org/schema/batch">
<step id="sample-db-to-multi-item-001" next="sample-db-to-multi-item-002">
<tasklet>
<chunk reader="SmpDbToMultiItemChunk" processor="SmpDbToMultiItemChunk" writer="w-sample-db-to-multi-item-001" />
</tasklet>
</step>
<step id="sample-db-to-multi-item-002">
<tasklet>
<chunk reader="SmpDbToMultiItemChunk" processor="SmpDbToMultiItemChunk" writer="w-sample-db-to-multi-item-002" />
</tasklet>
</step>
</job>
<!--
* 샘플용직원정보 Multi Type Fixed File을 Write 하기위한 bean 설정
-->
<bean id="w-sample-db-to-multi-item-001" parent="WMultiTypeFix" scope="step">
<property name="name" value="w-sample-db-to-multi-item-001" />
<property name="resource" value="file:///${prefixFilePath}/test-multi-fixed-file-#{jobParameters['deptNo']}.txt" />
<property name="targetType" value="sample.batch.service.dto.SmpDbToMultiItemChunkMasterDto" />
</bean>
<!--
* 샘플용직원정보 Multi Type Delimited File을 Write 하기위한 bean 설정
-->
<bean id="w-sample-db-to-multi-item-002" parent="WMultiTypeDelimit" scope="step">
<property name="name" value="w-sample-db-to-multi-item-002" />
<property name="resource" value="file:///${prefixFilePath}/test-multi-delimited-file-#{jobParameters['deptNo']}.txt" />
<property name="targetType" value="sample.batch.service.dto.SmpDbToMultiItemChunkMasterDto" />
<property name="delimiter" value=";" />
</bean>
</beans>
-
배치 소스코드 Sample
package sample.batch.service;
import java.math.BigDecimal;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import bxm.common.annotaion.BxmCategory;
import bxmc.batch.ext.context.DefaultBatchApplicationContext;
import bxmc.common.util.DateUtils;
import bxmc.config.dbio.util.DasUtils;
import bxmc.core.ext.context.DefaultApplicationContext;
import sample.batch.dbio.DSmpEmpBat001;
import sample.batch.dbio.dto.DSmpEmpBat000Dto;
import sample.batch.service.dto.SmpDbToMultiItemChunkBodyDto;
import sample.batch.service.dto.SmpDbToMultiItemChunkFooterDto;
import sample.batch.service.dto.SmpDbToMultiItemChunkHeaderDto;
import sample.batch.service.dto.SmpDbToMultiItemChunkMasterDto;
/**
* 샘플 DB TO FILE(Multi Item/Type) 배치
*
* @author sysadmin
*/
@Scope("step")
@Service("SmpDbToMultiItemChunk")
@BxmCategory(logicalName="샘플 DB TO FILE(Multi Item/Type) 배치", description="샘플 DB TO FILE(Multi Item/Type) 배치")
public class SmpDbToMultiItemChunk implements ItemStream, ItemReader<SmpDbToMultiItemChunkBodyDto>, ItemProcessor<SmpDbToMultiItemChunkBodyDto, SmpDbToMultiItemChunkMasterDto>{
private Logger logger= LoggerFactory.getLogger(getClass());
private DSmpEmpBat001 dSmpEmpBat001;
private Iterator<DSmpEmpBat000Dto> iterator;
private int count = 0;
private long jobInstanceId;
private String writeDate = null;
private String writeTime = null;
/**
* open
* - 초기화를 위해 구현해야 하는 Method 로서 스텝이 시작되기 전에 FW에서 최초 1번 호출된다.
*/
@Override
@BxmCategory(logicalName = "open : 샘플용 직원정보 Iterator 처리", description = "open : 샘플용 직원정보 Iterator 처리")
public void open(ExecutionContext executionContext) throws ItemStreamException {
// getBean
dSmpEmpBat001 = DefaultApplicationContext.getBean(dSmpEmpBat001, DSmpEmpBat001.class);
// 부서번호 파라미터 확인
String deptNoStr = DefaultBatchApplicationContext.getJobParameter("deptNo");
if(deptNoStr == null) {
throw new ItemStreamException("deptNo is null or empty.");
}
int deptNo = Integer.valueOf(deptNoStr);
// 부서번호에 해당하는 사원 조회
iterator = dSmpEmpBat001.selectList01(deptNo).iterator();
}
@BeforeStep
public void beforeStep(StepExecution stepExecution)
{
jobInstanceId = stepExecution.getJobExecution().getJobInstance().getInstanceId();
writeDate = DateUtils.getDateNow();
writeTime = DateUtils.getDateTimeNow();
}
/**
* read
* - 처리 대상 데이터를 건 별로 DB 또는 파일에서 읽어오는 역할을 수행한다.
*/
@Override
@BxmCategory(logicalName = "read : 샘플용 직원정보 Read", description = "read : 샘플용 직원정보를 1건씩 Read한다.")
public SmpDbToMultiItemChunkBodyDto read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
SmpDbToMultiItemChunkBodyDto out = null;
if(iterator.hasNext()) {
out = new SmpDbToMultiItemChunkBodyDto();
DSmpEmpBat000Dto input = iterator.next();
out.setFeduEmpNo(input.getFeduEmpNo()); // FW샘플 임직원번호
out.setFeduEmpNm(input.getFeduEmpNm()); // FW샘플 임직원명
out.setFeduOccpNm(input.getFeduOccpNm()); // FW샘플 직업명
out.setFeduMngrEmpNo(input.getFeduMngrEmpNo()); // FW샘플 관리자임직원번호
out.setFeduHireDt(input.getFeduHireDt()); // FW샘플 입사일자
out.setFeduPayAmt(input.getFeduPayAmt()); // FW샘플 급여금액
out.setFeduDeptNo(input.getFeduDeptNo()); // FW샘플 부서번호
// 마지막 Item 설정
if(!iterator.hasNext()) {
DefaultBatchApplicationContext.setLastReader(out);
}
}
return out;
}
/**
* process
* - 처리 대상 데이터를 건 별로 업무요건에 따라 처리하는 역할을 수행한다.
*/
@Override
@BxmCategory(logicalName = "process : 샘플용 직원정보 처리", description = "process : 샘플용 직원정보를 1건씩 처리한다.")
public SmpDbToMultiItemChunkMasterDto process(SmpDbToMultiItemChunkBodyDto in) throws Exception {
count++;
SmpDbToMultiItemChunkMasterDto out = new SmpDbToMultiItemChunkMasterDto();
/**
* Header 처리
*/
if(count == 1) {
SmpDbToMultiItemChunkHeaderDto header = new SmpDbToMultiItemChunkHeaderDto();
header.setJobInstanceId(new BigDecimal(jobInstanceId));
header.setWriteDate(writeDate);
header.setWriteTime(writeTime);
out.setHeader(header);
}
/**
* Body 처리
*/
SmpDbToMultiItemChunkBodyDto body = new SmpDbToMultiItemChunkBodyDto();
body.setFeduEmpNo(in.getFeduEmpNo()); // FW샘플 임직원번호
body.setFeduEmpNm(in.getFeduEmpNm()); // FW샘플 임직원명
body.setFeduOccpNm(in.getFeduOccpNm()); // FW샘플 직업명
body.setFeduMngrEmpNo(in.getFeduMngrEmpNo()); // FW샘플 관리자임직원번호
body.setFeduHireDt(in.getFeduHireDt()); // FW샘플 입사일자
body.setFeduPayAmt(in.getFeduPayAmt()); // FW샘플 급여금액
body.setFeduDeptNo(in.getFeduDeptNo()); // FW샘플 부서번호
out.setBody(body);
/**
* Footer 처리
*/
if(DefaultBatchApplicationContext.isLastReaderItem(in)){
SmpDbToMultiItemChunkFooterDto footer = new SmpDbToMultiItemChunkFooterDto();
footer.setCount(count);
out.setFooter(footer);
}
return out;
}
/**
* update
* - 진행 상태를 기록하기 위해 구현해야 하는 Method로서 구간 별로 Commit 시에 FW에서 호출된다.
*/
@Override
@BxmCategory(logicalName = "update", description = "update")
public void update(ExecutionContext executionContext) throws ItemStreamException {
logger.info("= Count : {}", new Object[] {count});
}
/**
* close
* - 리소스 정리 작업을 위해 구현해야 하는 Method로서 Step 완료 시에 FW에서 호출된다.
*/
@Override
@BxmCategory(logicalName = "close", description = "close")
public void close() throws ItemStreamException {
// Close 처리
if(iterator != null) DasUtils.closeCursor(iterator);
}
}