2012-03-05 7 views
16

Potrzebuję wstawić tysiące rekordów w bazie danych za jednym razem. Korzystam ze sprężynowego szablonu JDBC w mojej aplikacji.Jak wykonać wiele wstawek w bazie danych za pomocą wiosennego pliku szablonu JDBC?

Poniżej znajduje się kod, który napisałem do tej pory, który wykonuje wszystkie wkładki za jednym razem. Tak więc, jeśli mam 10 000 użytkowników, są one wstawiane za jednym razem. Ale chcę je wykonać w partiach, powiedzmy na przykład 500 rekordów w jednej partii i tak dalej.

@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(); 
       } 
      }); 

} 

Jak mogę zmienić powyższy kod tak, że zamiast employeeList.size() jako wielkości partii możemy mieć wielkość wsadu jak powiedzieć 500, a następnie wykonać je obok 500 i tak dalej?

Proszę o pomoc.

+0

Wiem, że to pytanie jest dość stary, ale mam pytanie. Dlaczego po prostu nie zwróciłeś 500 w metodzie 'getBatchSize'? –

Odpowiedz

21

Nie jestem pewien, czy można to zrobić za pomocą samego szablonu JDBC. Być może możesz wywołać metodę batchUpdate w kilku krokach, dzieląc dużą listę na porcje o rozmiarze wsadowym.

Sprawdźcie tutaj:

@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

Wiem, że to trochę późno, ale można zrobić coś podobnego do tego, co @adarshr robi, z wyjątkiem użycia Google Guava Lists.partition uzyskać listy zagnieżdżone.

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

Wciąż uproszczony sposób modyfikuje sposób getBatchsize() jak w poniżej działa dobrze

Nie ma potrzeby partycjonowania lub podzbioru listy :)

@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

To nie zadziała, ale wstawi tylko 500 pierwszych rekordów do bazy danych. – 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

Dzięki za odpowiedź. Wygląda o wiele czystsze. Miałem kilka wątpliwości: 1) co oznacza tablica 2D jako odpowiedź metody batchUpdate 2) Czy możemy sprawdzić w trakcie działania aplikacji, że dboperations faktycznie działa w partiach? – Ankit

Powiązane problemy