在项目中,如果需要一次性插入或更新多条记录,当然可以简单地通过多次调用update()方法完成任务,但这不是最好的实现方案。更好的选择是使用JDBCTemplate批量数据更改的方法。一般情况下,后者拥有更好的性能,因为更新的数据将被批量发送到数据库中,它减少了对数据库访问的次数。JDBC有2个批量数据操作的方法:
public int[] batchUpdate(String[] sql)
多条SQL语句组成一个数组,注意此处的sql语句不能带参数,该方法以批量方式执行这些SQL语句。Spring在内部使用JDBC提供的批量更新API完成操作,如果底层的JDBC Driver不支持批量更新操作,Spring将采用逐条更新的方式模拟批量更新。
int[] batchUpdate(Stringsql,BatchPreparedStatementSetter pss)
使用本方法对于同一结构的带参SQL语句多次进行数据更新操作。通过BatchPreparedStatementSetter回调接口进行批量参数的绑定工作。BatchPreparedStatementSetter定义了两个方法:
int getBatchSize():指定本批次的大小
void setValues(PreparedStatement ps,int i):为给定的PreparedStatement设置参数
示例如下:
private void addUsers(finalList<User> userList) {
final String sql = "insert into user(username,age)values(?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int index) throwsSQLException {
User user =userList.get(index);
ps.setString(1,user.getUsername());
ps.setInt(2, user.getAge());
}
public int getBatchSize() {
return userList.size();
}
});
}
需要注意的是BatchPreparedStatementSetter是一次性地批量提交数据,而不会分批提交,getBatchSize()是整批的大小。所以,如果希望将一个List中的数据通过BatchPreparedStatementSetter批量更新到数据库中,getBatchSize()就应该设置为List的大小。如果List非常大,希望分多次批量提交,则可分段读取这个大List并暂存到一个小的List中,再将这个小的List通过BatchPreparedStatemetSetter批量保存到数据库中。
public voidbatchInsertRows(String sql,final List<Object[]> dataSet) throwsException{
BatchPreparedStatementSetter setter=new BatchPreparedStatementSetter(){
public int getBatchSize(){
return dataSet.size();
}
public void setValues(PreparedStatement ps,inti){
Object[] obj = dataSet.get(i);
int nextId = getNextId();
try{
ps.setLong(1,nextId);
ps.setLong(2,Integer.parseInt(obj[0].toString()));
ps.setLong(3,Integer.parseInt(obj[1].toString()));
ps.setString(4,(String)obj[2]);}
catch(Exception e){
e.printStackTrace();
}
}
};
jdbcTemplate.batchUpdate(sql,setter);
}