Как сделать несколько вставок в базу данных, используя шаблон JDBC Spring? - PullRequest
17 голосов
/ 05 марта 2012

Мне нужно вставить тысячи записей в базу данных за один раз.Я использую шаблон Spring JDBC в своем приложении.

Ниже приведен код, который я написал до сих пор, который выполняет все вставки за один раз.Итак, если у меня есть 10000 пользователей, они вставляются за один раз.Но я хочу, чтобы они выполнялись партиями, например, 500 записей в одной партии и так далее.

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

}

Как изменить приведенный выше код, чтобы вместо employeeList.size () в качестве размера пакета мы могли иметь размер пакета, например, 500, выполнить их, а затем следующие 500 и т. Д.?

Пожалуйста, помогите.

Ответы [ 4 ]

24 голосов
/ 05 марта 2012

Я не уверен, что вы можете сделать это, используя только шаблон JDBC. Возможно, вы могли бы вызвать метод batchUpdate поэтапно, разделив большой список на куски размером в пакет.

Посмотрите здесь:

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

    }
}
16 голосов
/ 23 января 2013

Я знаю, что уже немного поздно, но вы можете сделать что-то похожее на то, что делает @adarshr, за исключением использования Google Guava Lists.partition для получения подсписков.

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();
            }
        });
    }
}
4 голосов
/ 13 октября 2015

Spring обеспечивает пакетные операции с несколькими партиями.В приведенном ниже примере размер партии равен 100.

 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 голосов
/ 04 июня 2015

Все еще упрощенным способом является модификация метода getBatchsize (), как показано ниже.

Нет необходимости разбиения или подмножества списка:),

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