2012-03-05 12 views
16

Necesito insertar miles de registros en la base de datos de una vez. Estoy usando la plantilla primavera JDBC en mi aplicación.¿Cómo hacer varias inserciones en la base de datos utilizando el lote de plantillas JDBC de primavera?

A continuación se muestra el código que he escrito hasta ahora que ejecuta todas las inserciones de una vez. Entonces, si tengo 10,000 usuarios, se insertan de una vez. Pero lo que quiero es ejecutarlos en lotes, por ejemplo, 500 registros en un lote, etc.

@Override 
public void saveBatch(final List<Employee> employeeList) { 
    final int batchSize = 500; 

    getJdbcTemplate().batchUpdate(QUERY_SAVE, 
      new BatchPreparedStatementSetter() { 
       @Override 
       public void setValues(PreparedStatement ps, int i) 
         throws SQLException { 
        Employee employee = employeeList.get(i); 
        ps.setString(1, employee.getFirstname()); 
        ps.setString(2, employee.getLastname()); 
        ps.setString(3, employee.getEmployeeIdOnSourceSystem()); 
       } 

       @Override 
       public int getBatchSize() { 
        return employeeList.size(); 
       } 
      }); 

} 

¿Cómo se cambia el código anterior para que en lugar de employeeList.size() como el tamaño del lote podemos tener el tamaño del lote, como dicen 500, ejecutarlos y luego al lado 500 y así sucesivamente?

Por favor ayuda.

+0

Sé que esta pregunta es bastante viejo, pero tengo una pregunta. ¿Por qué no devolviste 500 en el método 'getBatchSize'? –

Respuesta

21

No estoy seguro de poder hacer eso solo con la plantilla JDBC. Tal vez podría invocar el método batchUpdate en pasos, dividiendo la lista grande en fragmentos del tamaño de un lote.

un vistazo aquí:

@Override 
public void saveBatch(final List<Employee> employeeList) { 
    final int batchSize = 500; 

    for (int j = 0; j < employeeList.size(); j += batchSize) { 

     final List<Employee> batchList = employeeList.subList(j, j + batchSize > employeeList.size() ? employeeList.size() : j + batchSize); 

     getJdbcTemplate().batchUpdate(QUERY_SAVE, 
      new BatchPreparedStatementSetter() { 
       @Override 
       public void setValues(PreparedStatement ps, int i) 
         throws SQLException { 
        Employee employee = batchList.get(i); 
        ps.setString(1, employee.getFirstname()); 
        ps.setString(2, employee.getLastname()); 
        ps.setString(3, employee.getEmployeeIdOnSourceSystem()); 
       } 

       @Override 
       public int getBatchSize() { 
        return batchList.size(); 
       } 
      }); 

    } 
} 
14

Sé que es un poco tarde, pero se podría hacer algo similar a lo que está haciendo @adarshr, excepto el uso Google Guava Lists.partition para conseguir las sublistas.

public void saveBatch(final List<Employee> employeeList) { 
    final int batchSize = 500; 
    List<List<Employee>> batchLists = Lists.partition(employeeList, batchSize); 

    for(List<Employee> batch : batchLists) { 
     getJdbcTemplate().batchUpdate(QUERY_SAVE, new BatchPreparedStatementSetter() { 
      @Override 
      public void setValues(PreparedStatement ps, int i) 
        throws SQLException { 
       Employee employee = batch.get(i); 
       ps.setString(1, employee.getFirstname()); 
       ps.setString(2, employee.getLastname()); 
       ps.setString(3, employee.getEmployeeIdOnSourceSystem()); 
      } 

      @Override 
      public int getBatchSize() { 
       return batch.size(); 
      } 
     }); 
    } 
} 
0

manera simplificada Aún está modificando el método getBatchsize() como en la de abajo funciona bien

No hay necesidad de partición o un subconjunto de la lista :),

@Override 
public void saveBatch(final List<Employee> employeeList) { 
    final int batchSize = 500; 
    getJdbcTemplate().batchUpdate(QUERY_SAVE, 
      new BatchPreparedStatementSetter() { 
       @Override 
       public void setValues(PreparedStatement ps, int i) 
         throws SQLException { 
        Employee employee = employeeList.get(i); 
        ps.setString(1, employee.getFirstname()); 
        ps.setString(2, employee.getLastname()); 
        ps.setString(3, employee.getEmployeeIdOnSourceSystem()); 
       } 

       @Override 
       public int getBatchSize() { 
        if (batchSize > employeeList.size()) { 
         return employeeList.size(); 
        } 
        return batchSize; 
       } 
      }); 
} 
+0

Esto no funcionará, pero solo inserte los primeros 500 registros en la base de datos. – ngeek

3
Spring provide Batch operations with multiple batches 
here 100 is batch size. 


public class JdbcActorDao implements ActorDao { 

    private JdbcTemplate jdbcTemplate; 

    public void setDataSource(DataSource dataSource) { 
     this.jdbcTemplate = new JdbcTemplate(dataSource); 
    } 

    public int[][] batchUpdate(final Collection<Actor> actors) { 
     int[][] updateCounts = jdbcTemplate.batchUpdate(
       "update t_actor set first_name = ?, last_name = ? where id = ?", 
       actors, 
       100, 
       new ParameterizedPreparedStatementSetter<Actor>() { 
        public void setValues(PreparedStatement ps, Actor argument) throws SQLException { 
         ps.setString(1, argument.getFirstName()); 
         ps.setString(2, argument.getLastName()); 
         ps.setLong(3, argument.getId().longValue()); 
        } 
       }); 
     return updateCounts; 
    } 

    // ... additional methods 

} 
+0

Gracias por su respuesta. Se ve mucho más limpio. Tenía pocas dudas: 1) ¿Qué significa la matriz 2D como respuesta del método batchUpdate? 2) ¿Podemos verificar de forma cruzada durante la ejecución de la aplicación que dboperations realmente se está ejecutando en lotes? – Ankit

Cuestiones relacionadas