Twitter
- 얼마전부터 아이폰 메일에서 메일 본문이 보이지 않아요. 혹시 해결책 아는 분 없나요? 5 hrs ago
- 제주장애인인권포럼에서 8월 한달간 '웹접근성'에 대해 교육해줄 수 있는 분을 찾습니다. 교육 내용은 http://njpaiks.egloos.com 에 정리된 내용 정도면 되고, 장애인 대상으로 주 4회 강의, 강사비도 지급됩니다. 7 hrs ago
- Facebook like 버튼에 comment도 넣을 수 있다. view 추천평은 성공하지 못했는데 Facebook은 어떨지... 아이덴티티가 강한 자신만의 홈페이지가 있으니 다르게 발전하겠지. 소셜 Q&A도 기대된다. 1 day ago
- More updates...
Posting tweet...
Powered by Twitter Tools
카테고리
- Java (14)
- Ruby & Languages (4)
- Software & Developer (58)
- 고양이 이야기 (8)
- 그들의 이야기 (13)
- 깨달음으로 가는 길 (49)
- 제주 생활 (11)
-
최근 작성글
-
최근 덧글
- 따지크 on NoSQL 정의와 사례 정리
- 에너 on NoSQL 정의와 사례 정리
- 성게군 on NoSQL 정의와 사례 정리
iBatis에서 batch 기능 활용하기
iBatis는 아래와 같은 방법으로 batch 처리가 가능하다. iBatis 내부 코드를 확인해 본 바로는 PreparedStatement.addBatch()를 사용하고 있고, 동일한 쿼리가 반복해서 들어올 때 하나의 batch로 처리해준다.
try { SqlMapClient.startTransaction(); SqlMapClient.startBatch(); while (...) { SqlMapClient.insert(query, params); } SqlMapClient.executeBatch(); SqlMapClient.commitTransaction(); } catch (Exception e) { log.error(e, e); } finally { SqlMapClient.endTransaction(); }이 기능을 활용해서 BatchManager를 만들어서 사용하고 있는데, 사용자의 로그인 시간을 기록하거나 게시물의 조회수를 늘리는 등 빈번하게 동일한 update가 발생하는 서비스에 사용하면 효과가 있다.
사용법은 기존의 서비스 코드 수정을 최소화하는 방법으로 고안했다. SqlMapClient.insert(query, params)를 BatchManager.insert(query, params)로 수정하면 된다.
관련 코드)
BatchManager.java
public class BatchManager { private static BatchWorker worker = BatchWorker.getInstance(); static { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { worker.flushAll(); worker.stop(); } catch (Exception e) { e.printStackTrace(); } } }); } public static void insert(String query, Object params) { worker.put(new BatchQuery(INSERT, query, params)); } public static void update(String query, Object params) { worker.put(new BatchQuery(UPDATE, query, params)); } }BatchWorker.java
public class BatchWorker { public static final int HEARTBEAT = 1000; public static int MAX_WAIT = 30000; public static final int SIZE_OF_ONE_BATCH = 200; public static final int MAX_SIZE = 100; private long lastTime; private final Timer timer; private Vector queue;
private static BatchWorker singletonWorker;
private BatchWorker() {
lastTime = System.currentTimeMillis();
timer = new Timer(true);
queue = new Vector();
startWorker();
}
public static synchronized BatchWorker getInstance() {
if (singletonWorker == null)
singletonWorker = new BatchWorker();
return singletonWorker;
}
private void startWorker() {
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
doBatch();
} catch (Exception e) {
// ignore
e.printStackTrace();
}
}
}, 0, HEARTBEAT);
}
private void doBatch() {
if (System.currentTimeMillis() - lastTime > MAX_WAIT
|| queue.size() >= MAX_SIZE) {
executeQuery();
lastTime = System.currentTimeMillis();
}
}
private synchronized void executeQuery() {
if (queue.size() == 0)
return;
try {
int cnt = 0;
SqlMapClient.startTransaction();
SqlMapClient.startBatch();
while (cnt++ < SIZE_OF_ONE_BATCH) {
if (queue.size() == 0)
break;
BatchQuery batchQuery = queue.remove(0);
switch (batchQuery.type) {
case INSERT:
SqlMapClient.insert(batchQuery.query, batchQuery.params);
break;
case UPDATE:
SqlMapClient.update(batchQuery.query, batchQuery.params);
break;
default:
break;
}
}
SqlMapClient.executeBatch();
SqlMapClient.commitTransaction();
} catch (Exception e) {
log.error(e, e);
} finally {
SqlMapClient.endTransaction();
}
}
public int size() {
return queue.size();
}
public void put(BatchQuery query) {
queue.add(query);
}
public void flushAll() {
while (queue.size() > 0)
executeQuery();
}
public void stop() {
timer.cancel();
}
}
BatchQuery.java
public class BatchQuery { public enum QueryType { INSERT, UPDATE } public String query; public Object params; public QueryType type; public BatchQuery(QueryType type, String query, Object params) { this.type = type; this.query = query; this.params = params; } }참고)