code: @Override
      public int[] withBatch(int batchSize, Closure closure) throws SQLException {
          batchData = new ArrayList<Object>();
          withinDataSetBatch = true;
          closure.call(this);
          withinDataSetBatch = false;
          if (batchData.isEmpty()) {
              return EMPTY_INT_ARRAY;
          }
          Closure transformedClosure = new Closure(null) {
              public void doCall(BatchingPreparedStatementWrapper stmt) throws SQLException {
                  for (Object next : batchData) {
                      stmt.addBatch(new Object[]{next});
                  }
              }
          };
          return super.withBatch(batchSize, buildMapQuery(), transformedClosure);
      }
docs: Performs the closure (containing batch operations) within a batch.
  For example:
  <pre>
  dataSet.withBatch(3) {
  add(anint: 1, astring: "Groovy")
  add(anint: 2, astring: "rocks")
  add(anint: 3, astring: "the")
  add(anint: 4, astring: "casbah")
  }
  </pre>
  
  @param batchSize partition the batch into batchSize pieces, i.e. after batchSize
  <code>addBatch()</code> invocations, call <code>executeBatch()</code> automatically;
  0 means manual calls to executeBatch are required
  @param closure   the closure containing batch and optionally other statements
  @return an array of update counts containing one element for each
  command in the batch.  The elements of the array are ordered according
  to the order in which commands were added to the batch.
  @throws SQLException if a database access error occurs, or the driver does not support batch statements.
  Throws {@link java.sql.BatchUpdateException} (a subclass of <code>SQLException</code>)
  if one of the commands sent to the database fails to execute properly.