[IBatis]sqlMap.executeBatch()의 반환값이 항상 0으로 나오는 경우...

Jakarta 2007. 12. 10. 14:07
대량의 반복되는 SQL 구문을 일괄 적용해야 하는 경우,
 iBatis에서는 executeBatch()라는 API를 지원합니다.
보통 아래의 구문으로 사용되죠.
 try {
    sqlMap = SqlMapManager.getSqlMap();
    sqlMap.startTransaction();
    sqlMap.startBatch ();
    for (int i=0 ; i < 10 ; i++) {
        sqlMap.update("namespace.sqlId", "some_parameters");
     }
     sqlMap.executeBatch(); // 이 경우 결과가 항상 '0'임
     sqlMap.commitTransaction();
}
finally {
     sqlMap.endTransaction();
}
iBatis 내부 소스를 살펴보니 아래와 같이 해당 소스가 구현되어 있었습니다.
public int executeBatch() throws SQLException {
    int totalRowCount = 0;
    for (int i = 0, n = statementList.size(); i < n; i++) {
        PreparedStatement ps = (PreparedStatement) statementList.get(i);
        int[] rowCounts = ps.executeBatch();
        for (int j = 0; j < rowCounts.length; j++) {
            if (rowCounts[j] == Statement.SUCCESS_NO_INFO) { // ----> SQL이 성공할 경우 항상 여기를 거침 // do nothing
            }
            else if (rowCounts[j] == Statement.EXECUTE_FAILED) {
                throw new SQLException("The batched statement at index " + j + " failed to execute.");
            }
            else {
                totalRowCount += rowCounts[j];
            }
        }
    }
    return totalRowCount;
}
위 소스에서 오라클의 경우 항상 Statement.SUCCESS_NO_INFO = -2 의 값을 반환하므로
 그 아래 구문인 totalRowCount += rowCounts[j]; 로 로직이 걸러지지 않아 항상 '0'을 반환하게 되는 구조입니다.
따라서 위 소스를 상속받아 직접 패치(오버라이딩)하고자 했으나 위 소스의 생성자가 다른 부분에서 직접 new를 통해 명시되는 구조이기 때문에 아래 API를 사용하시기를 권고해 드립니다.
 public java.util.List executeBatchDetailed() 배치작업을 통해 적용된 로우의 수는 위에서 반환된 list.size()를 통해 얻으시면 됩니다. 또는, iBatis 내부에서 배치작업 시 발생하는 예외는 항상 호출자에게 던지는 구조이기 때문에 예외가 발생하지 않았을 경우에는 모든 배치작업이 성공적으로 완료되었다고 가정하셔도 무방합니다.
따라서 executeBatch() 호출 시 에러가 발생하지 않았다면 대상 배치대상 로우가 모두 정상적으로 실행되었다고
보고 로직을 구현하시면 됩니다. 이와 관련한 iBatis 이슈트래킹 정보는 아래 주소를 참조하세요.
 

설정

트랙백

댓글