我需要一次性在数据库中插入数千条记录。我在我的应用程序中使用spring JDBC模板。
下面是我到目前为止编写的代码,它一次执行所有插入。所以,如果我有10,000个用户,他们一次插入。但我想要的是批量执行它们,例如一批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,依此类推?
请帮忙。
答案 0 :(得分:23)
我不确定你是否可以单独使用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();
}
});
}
}
答案 1 :(得分:16)
我知道这有点晚了但你可以做类似于@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();
}
});
}
}
答案 2 :(得分:4)
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
}
答案 3 :(得分:-1)
仍然简化的方法是修改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;
}
});
}