private List<Object[]> buildStepExecutionParameters(StepExecution stepExecution) {
   Assert.isNull(
       stepExecution.getId(),
       "to-be-saved (not updated) StepExecution can't already have an id assigned");
   Assert.isNull(
       stepExecution.getVersion(),
       "to-be-saved (not updated) StepExecution can't already have a version assigned");
   validateStepExecution(stepExecution);
   stepExecution.setId(stepExecutionIncrementer.nextLongValue());
   stepExecution.incrementVersion(); // Should be 0
   List<Object[]> parameters = new ArrayList<Object[]>();
   String exitDescription =
       truncateExitDescription(stepExecution.getExitStatus().getExitDescription());
   Object[] parameterValues =
       new Object[] {
         stepExecution.getId(),
         stepExecution.getVersion(),
         stepExecution.getStepName(),
         stepExecution.getJobExecutionId(),
         stepExecution.getStartTime(),
         stepExecution.getEndTime(),
         stepExecution.getStatus().toString(),
         stepExecution.getCommitCount(),
         stepExecution.getReadCount(),
         stepExecution.getFilterCount(),
         stepExecution.getWriteCount(),
         stepExecution.getExitStatus().getExitCode(),
         exitDescription,
         stepExecution.getReadSkipCount(),
         stepExecution.getWriteSkipCount(),
         stepExecution.getProcessSkipCount(),
         stepExecution.getRollbackCount(),
         stepExecution.getLastUpdated()
       };
   Integer[] parameterTypes =
       new Integer[] {
         Types.BIGINT,
         Types.INTEGER,
         Types.VARCHAR,
         Types.BIGINT,
         Types.TIMESTAMP,
         Types.TIMESTAMP,
         Types.VARCHAR,
         Types.INTEGER,
         Types.INTEGER,
         Types.INTEGER,
         Types.INTEGER,
         Types.VARCHAR,
         Types.VARCHAR,
         Types.INTEGER,
         Types.INTEGER,
         Types.INTEGER,
         Types.INTEGER,
         Types.TIMESTAMP
       };
   parameters.add(0, Arrays.copyOf(parameterValues, parameterValues.length));
   parameters.add(1, Arrays.copyOf(parameterTypes, parameterTypes.length));
   return parameters;
 }
 @Test
 public void testSkipsInWriter() throws Exception {
   JobExecution jobExecution =
       jobLauncher.run(
           job,
           new JobParametersBuilder()
               .addString("item.three", "fail")
               .addLong("run.id", 1L)
               .toJobParameters());
   assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
   StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
   assertEquals(9, stepExecution.getReadCount());
   assertEquals(7, stepExecution.getWriteCount());
   // The whole chunk gets skipped...
   assertEquals(2, stepExecution.getWriteSkipCount());
 }
  @Override
  public void updateStepExecution(StepExecution stepExecution) {

    validateStepExecution(stepExecution);
    Assert.notNull(
        stepExecution.getId(),
        "StepExecution Id cannot be null. StepExecution must saved" + " before it can be updated.");

    // Do not check for existence of step execution considering
    // it is saved at every commit point.

    String exitDescription =
        truncateExitDescription(stepExecution.getExitStatus().getExitDescription());

    // Attempt to prevent concurrent modification errors by blocking here if
    // someone is already trying to do it.
    synchronized (stepExecution) {
      Integer version = stepExecution.getVersion() + 1;
      Object[] parameters =
          new Object[] {
            stepExecution.getStartTime(),
            stepExecution.getEndTime(),
            stepExecution.getStatus().toString(),
            stepExecution.getCommitCount(),
            stepExecution.getReadCount(),
            stepExecution.getFilterCount(),
            stepExecution.getWriteCount(),
            stepExecution.getExitStatus().getExitCode(),
            exitDescription,
            version,
            stepExecution.getReadSkipCount(),
            stepExecution.getProcessSkipCount(),
            stepExecution.getWriteSkipCount(),
            stepExecution.getRollbackCount(),
            stepExecution.getLastUpdated(),
            stepExecution.getId(),
            stepExecution.getVersion()
          };
      int count =
          getJdbcTemplate()
              .update(
                  getQuery(UPDATE_STEP_EXECUTION),
                  parameters,
                  new int[] {
                    Types.TIMESTAMP,
                    Types.TIMESTAMP,
                    Types.VARCHAR,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.VARCHAR,
                    Types.VARCHAR,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.INTEGER,
                    Types.TIMESTAMP,
                    Types.BIGINT,
                    Types.INTEGER
                  });

      // Avoid concurrent modifications...
      if (count == 0) {
        int curentVersion =
            getJdbcTemplate()
                .queryForObject(
                    getQuery(CURRENT_VERSION_STEP_EXECUTION),
                    new Object[] {stepExecution.getId()},
                    Integer.class);
        throw new OptimisticLockingFailureException(
            "Attempt to update step execution id="
                + stepExecution.getId()
                + " with wrong version ("
                + stepExecution.getVersion()
                + "), where current version is "
                + curentVersion);
      }

      stepExecution.incrementVersion();
    }
  }