Source:
<code>public Object invoke(Object target, Method method, Object[] args, HandleSupplier h) { final Handle handle = h.getHandle(); final String sql = handle.getConfig().get(SqlObjects.class) .getSqlLocator().locate(sqlObjectType, method); final int chunkSize = batchChunkSize.call(args); final Iterator<Object[]> batchArgs = zipArgs(args); ResultIterator<Object> result = new ResultIterator<Object>() { ResultIterator<?> batchResult; { hasNext(); } @Override public boolean hasNext() { if (batchResult != null) { if (batchResult.hasNext()) { return true; } batchResult.close(); } if (!batchArgs.hasNext()) { return false; } PreparedBatch batch = handle.prepareBatch(sql); applyCustomizers(batch, args); for (int i = 0; i < chunkSize && batchArgs.hasNext(); i++) { applyBinders(batch.add(), batchArgs.next()); } batchResult = executeBatch(handle, batch); return hasNext(); } @Override public Object next() { if (!hasNext()) { throw new NoSuchElementException(); } return batchResult.next(); } @Override public StatementContext getContext() { return batchResult.getContext(); } @Override public void close() { <START> batchResult.close(); <END> } }; return magic.result(new ResultBearing<Object>() { @Override public <R> R execute(StatementExecutor<Object, R> executor) { throw new UnsupportedOperationException( "@SqlBatch currently does not support custom execution modes like reduce"); } @Override public ResultIterator<Object> iterator() { return result; } @Override public StatementContext getContext() { return result.getContext(); } }); }</code><technical_language>Nit: remember this method is called successive calls iterator continue executing more batches</technical_language>

Target:
public Object invoke(Object target, Method method, Object[] args, HandleSupplier h) { final Handle handle = h.getHandle(); final String sql = handle.getConfig().get(SqlObjects.class) .getSqlLocator().locate(sqlObjectType, method); final int chunkSize = batchChunkSize.call(args); final Iterator<Object[]> batchArgs = zipArgs(args); ResultIterator<Object> result = new ResultIterator<Object>() { ResultIterator<?> batchResult; boolean closed = false; { hasNext(); } @Override public boolean hasNext() { if (closed) { throw new IllegalStateException("closed"); } if (batchResult != null) { if (batchResult.hasNext()) { return true; } batchResult.close(); } if (!batchArgs.hasNext()) { return false; } PreparedBatch batch = handle.prepareBatch(sql); applyCustomizers(batch, args); for (int i = 0; i < chunkSize && batchArgs.hasNext(); i++) { applyBinders(batch.add(), batchArgs.next()); } batchResult = executeBatch(handle, batch); return hasNext(); } @Override public Object next() { if (closed) { throw new IllegalStateException("closed"); } if (!hasNext()) { throw new NoSuchElementException(); } return batchResult.next(); } @Override public StatementContext getContext() { return batchResult.getContext(); } @Override public void close() { closed = true; batchResult.close(); } }; return magic.result(new ResultBearing<Object>() { @Override public <R> R execute(StatementExecutor<Object, R> executor) { throw new UnsupportedOperationException( "@SqlBatch currently does not support custom execution modes like reduce"); } @Override public ResultIterator<Object> iterator() { return result; } @Override public StatementContext getContext() { return result.getContext(); } }); }