왜 쓰나?
대용량 데이터를 Row 단위 즉, 행별로 처리하기 위함.
(= SELECT와 INSERT,UPDATE,MERGE를 한 건씩 수행)
어떤 경우에 쓰이나?
필자의 경우 List에 70만건의 데이터를 담아서 처리하니 'GC overhead limit exceeded' 에러 발생 + OOM(Out Of Memory)에러 발생. 이를 해결하기 위해 썼다.
장점?
앞서 말한 것과 같이 '대용량 데이터'처리에 좋아 OOM에러를 피할 수 있다.(서버 멈추지 않기위해)
단점?
List에 담아서 처리하는 것 보다 훨~씬 느리다.
(그래서 시간 오래걸려도 상관없는 새벽시간 야음을 틈타 혼자 열심히 수행하는 Batch에 많이 쓰인다.)
본격적인 사용예시
<<Service.java 단>>
================================================================
public Map<String, Object> newSyncBatch(Map<String, Object> paramMap)
throws RuntimeException {
final StopWatch stopWatch = new StopWatch("NewSyncBatch");
Map<String, Object> result = new HashMap<String, Object>();
String endDt = "";
String strDt = "";
if(paramMap.get("strDt") == null && paramMap.get("endDt") == null) {
// 변경일시가 오늘로 부터 하루 전
strDt = EgovDateUtil.addYearMonthDay(EgovDateUtil.getToday(), 0, 0, -1);
endDt = EgovDateUtil.getToday();
} else{
strDt = MapUtil.getString(paramMap.get("strDt"));
endDt = MapUtil.getString(paramMap.get("endDt"));
}
stopWatch.start("실행날짜 : " + strDt + " ~ " + endDt + " 배치실행");
Map<String, Object> param = new HashMap<String, Object>();
param.put("endDt", endDt);
param.put("strDt", strDt);
// 확진자 정보(어제부터 오늘까지) - CI컬럼 없는 테이블 kdcadb
infoBatch(param);
stopWatch.stop();
logger.info("Batch 실행시간 : " + stopWatch.prettyPrint());
logger.info("Batch 실행 세부사항 : " + stopWatch.getTotalTimeSeconds() + "초");
return result;
}
private void infoBatch(Map<String, Object> param) {
dao.selectByHandler("scheduler.SELECT_NEW_SYNC",
param, new Handler(this, outsideDao ,param));
}
================================================================
step1. Service.java
infoBatch(param);
: 수행시키고자 하는 파라미터를 넘겨준다. 파라미터가 필요없으면 안 넘겨주는 메서드를 만들면 된다.
private void infoBatch(Map<String,Object> param
: dao에 만들어둔 selectByHandler 메서드에 맞게 파라미터들을 넘겨줘야 한다.
파라미터들 중 new Handler(this,~~) 이 부분 핵심** 아래 참고
dao.selectByHandler~~(this. outsideDao,~~) 이 부분 조심
필자는 다른 DB정보를 사용했기 때문에 'A' DB에서 select한 결과로 'B' DB에 Merge를 수행시킨다.
<<DAO 단>>
================================================================
@Repository
public class DsndgnssDao {
@Autowired
@Resource(name="sqlSessionDsndgnssTemplate")
private SqlSessionTemplate sqlSessionTemplate;
public void selectByHandler(String statementName, ResultHandler handler) {
sqlSessionTemplate.select(statementName, handler);
}
public void selectByHandler
(String statementName, Map param, ResultHandler handler) {
sqlSessionTemplate.select(statementName, param, handler);
}
}
================================================================
step2. DAO생성
: 기존 Dao.java에 메서드를 추가하면 된다.(당연 기호에 맞는 메서드명 혹은 명명규칙에 따른 메서드명)
: @Resource 부분은 해당 프로젝트에 맞는 환경설정을 한다.(DB프로퍼티 파일 같은데 설정 값이 있을 것)
<<Handler.java 단>>
================================================================
package com.abilsys.handler;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abilsys.dao.OutsideDao;
import com.abilsys.util.MapUtil;
import com.abilsys.web.service.DsndgnssBatchService;
public class DsndgnssHandler implements ResultHandler {
private OutsideDao outsideDao;
private DsndgnssBatchService dsndgnssBatchService;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private String strDt;
private String endDt;
public DsndgnssHandler
(DsndgnssBatchService dsndgnssBatchService, OutsideDao outsideDao, Map<String, Object> param)
{
this.dsndgnssBatchService = dsndgnssBatchService;
this.outsideDao = outsideDao;
this.strDt = MapUtil.getString(param.get("strDt"));
this.endDt = MapUtil.getString(param.get("endDt"));
}
@SuppressWarnings("unchecked")
@Override
public void handleResult(ResultContext resultContext) {
Map<String, Object> resultData = (Map<String, Object>) resultContext.getResultObject();
Map param = new HashMap<>();
String patntCI =
dsndgnssBatchService.getPatntCI(MapUtil.getString(resultData.get("PATNT_IHIDNUM"))
, MapUtil.getString(r esultData.get("DSNDGNSS_INNB")));
param.put("patnt_ci",patntCI);
param.put("dsndgnss_innb",resultData.get("DSNDGNSS_INNB"));
outsideDao.insert("dsndgnss_scheduler.MERGE_PA_DSNDGNSS_INFO_NEW", param);
}
}
================================================================
step3. Handler.java를 생성한다.
: 클래스파일을 따로 만든이유는 에러를 방지하기 위함.
메서드로 그냥 만들면 에러 날 수도 있단다.(어디서봤는데 기억안남)
: **중요** handleResult 메서드는 자동으로 만들어지고(?) 여튼 에러 밑줄 생기면(?) 생성하면 된다.
이 메서드는 내부적, 시스템적으로 handler가 알아서 호출을 한다.
**주의** 테스트라면 SELECT 되는 데이터를 넣어주자
DB에 데이터가 없으면 에러(null 에러)가 나고 삽질을 엄청 하게된다. 왜 안되지? 이 메서드 어디서 호출하지? ㅇㅈㄹ
'Language > JAVA' 카테고리의 다른 글
com.fasterxml.jackson.core.JsonParseException (0) | 2022.06.30 |
---|---|
JAVA에서 문자열을 ArrayList로 변환 및 ArrayList와 List의 차이점 (0) | 2022.04.11 |
log4j2 사용법 / 환경설정 / 패턴 layout / system.out 차이점 (0) | 2021.12.29 |
JavaMail로 회원가입 시 이메일 인증처리하기 (1) | 2021.07.28 |
상속(Inheritance) (0) | 2021.06.15 |