Spring JdbcTemplate使用實(shí)例
Spring NamedParameterJdbcTemplate的使用實(shí)例
前面我們用實(shí)例演示了如何使用JdbcTemplate和NamedParameterJdbcTemplate來對(duì)數(shù)據(jù)庫(kù)的增刪查改翩蘸,但是那些實(shí)例中都是針對(duì)單條記錄進(jìn)行操作,當(dāng)我們需要對(duì)一批數(shù)據(jù)進(jìn)行相同的SQL操作該怎么辦呢雕沿?總不能用for循環(huán)來遍歷n次吧不见,那也太低效了。
JdbcTemplate和NamedParameterJdbcTemplate當(dāng)然支持對(duì)數(shù)據(jù)庫(kù)的批量操作了程癌,通過以下實(shí)例你將了解到如何相對(duì)高效地執(zhí)行批量的SQL語(yǔ)句纷妆。
首先亦镶,我們需要在service的實(shí)現(xiàn)類中聲明兩個(gè)jdbcTemplate摹芙,后面需要使用它們進(jìn)行操作灼狰。
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private NamedParameterJdbcTemplate template;
現(xiàn)在我們針對(duì)JdbcTemplate來演示如何進(jìn)行數(shù)據(jù)庫(kù)SQL的批量操作:
@Override
public int[] batchUpdateGradeByName(List<Student> students) {
String sql = "update test_student set grade = ? where name = ?";
return this.jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, students.get(i).getGrade());
ps.setString(2, students.get(i).getName());
}
@Override
public int getBatchSize() {
return students.size();
}
});
}
@Test
public void batchUpdateGradeByName() {
Student s1 = new Student();
s1.setGrade("6");
s1.setName("李白");
Student s2 = new Student();
s2.setGrade("4");
s2.setName("杜甫");
List<Student> studentList = new ArrayList<>();
studentList.add(s1);
studentList.add(s2);
int[] nums = this.studentService.batchUpdateGradeByName(studentList);
assertEquals(new Integer("2"), new Integer(nums[0]));
assertEquals(new Integer("1"), new Integer(nums[1]));
}
在以上的代碼中,使用jdbcTemplate.batchUpdate
時(shí)浮禾,第二個(gè)參數(shù)是一個(gè)BatchPreparedStatementSetter的
匿名內(nèi)部類實(shí)例交胚,這個(gè)實(shí)例中我們必須要實(shí)現(xiàn)setValues
和getBatchSize
方法,其作用分別是替換SQL中占位符的值伐厌,以及獲取迭代執(zhí)行次數(shù)承绸。
以上方法可能會(huì)有些繁瑣裸影,當(dāng)然jdbcTemplate.batchUpdate
不止這一種使用方法挣轨,其第二個(gè)參數(shù)也能支持使用List,下面是對(duì)應(yīng)的代碼實(shí)例:
@Override
public int[] batchUpdateGradeByName(List<Student> student) {
String sql = "update test_student set grade = ? where name = ?";
List<Object[]> parameterList = new ArrayList<>();
for(Student s : student){
Object[] params = new Object[]{s.getGrade(), s.getName()};
parameterList.add(params);
}
return this.jdbcTemplate.batchUpdate(sql, parameterList);
}
在看完JdbcTemplate的使用方法后轩猩,我們?cè)賮砜纯词褂肗amedParameterJdbcTemplate的操作:
@Override
public int[] batchUpdateGradeByName(List<Student> student) {
String sql = "update test_student set grade = :grade where name = :name";
SqlParameterSource[] parameterSources = SqlParameterSourceUtils.createBatch(student);
return this.template.batchUpdate(sql, parameterSources);
}
這里我們使用了SqlParameterSource
來存放參數(shù)值卷扮,代碼量明顯少了很多,值得推薦均践。
最后一個(gè)例子來演示下晤锹,倘若我們有海量的數(shù)據(jù)需要批量操作到數(shù)據(jù)庫(kù)的場(chǎng)景。雖說JdbcTemplate和NamedParameterJdbcTemplate都支持批量操作彤委,但是也扛不住千鞭铆、萬(wàn)級(jí)別的數(shù)據(jù)同時(shí)更新呀,除非再次使用for循環(huán)焦影,拆成若干次來更新车遂?可以是可以,但是也太low了斯辰,其實(shí)JdbcTemplate內(nèi)部是支持指定數(shù)據(jù)量來分多次批量更新的舶担。
@Override
public int[][] batchUpdateGradeByName(List<Student> student) {
String sql = "update test_student set grade = ? where name = ?";
return this.jdbcTemplate.batchUpdate(sql, student, 100, new ParameterizedPreparedStatementSetter<Student>() {
@Override
public void setValues(PreparedStatement ps, Student student) throws SQLException {
ps.setString(1, student.getGrade());
ps.setString(2, student.getName());
}
});
}
最后說明一點(diǎn),這些操作返回的都是int類型的數(shù)組彬呻,代表著這批量執(zhí)行過程中衣陶,每一條SQL影響的記錄數(shù)柄瑰,最后一個(gè)例子是分次批量執(zhí)行,因此返回的是一個(gè)int類型的二維數(shù)組剪况。
總結(jié)下來教沾,使用JdbcTemplate和NamedParameterJdbcTemplate操作數(shù)據(jù)庫(kù)確實(shí)不像ORM框架那樣簡(jiǎn)潔便利,估計(jì)真實(shí)生產(chǎn)上用的人會(huì)很少吧译断。但無(wú)論如何详囤,這是學(xué)習(xí)Spring必不可少的一個(gè)環(huán)節(jié),了解一下還是很有必要的镐作。