在上一節(jié)的《Spring JdbcTemplate使用實(shí)例》中,我們?cè)诓樵?xún)返回對(duì)象的時(shí)候,使用了匿名類(lèi)來(lái)創(chuàng)建對(duì)象,看上去非常地不友好,代碼顯得很是冗長(zhǎng)難懂。那么本文就來(lái)先解釋下什么是Row Mapper,我們?cè)撊绾握_地使用。
@Override
public Student getStudentByName(String name) {
String sql = "select name, gender from test_student where name = ?";
Student student = this.jdbcTemplate.queryForObject(sql, new Object[]{name}, new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet rs, int i) throws SQLException {
Student s = new Student();
s.setName(rs.getString("name"));
s.setGender(rs.getString("gender"));
return s;
}
});
return student;
}
@Override
public List<Student> getStudentsByName(String name) {
String sql = "select name, gender from test_student where name = ?";
List<Student> students = this.jdbcTemplate.query(sql, new Object[]{name}, new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet rs, int i) throws SQLException {
Student s = new Student();
s.setName(rs.getString("name"));
s.setGender(rs.getString("gender"));
return s;
}
});
return students;
}
一、RowMapper的基本使用
使用過(guò)原生JDBC的朋友應(yīng)該知道,從數(shù)據(jù)庫(kù)查詢(xún)出來(lái)的記錄全都被保存在ResultSet結(jié)果集中,我們需要將結(jié)果集中的數(shù)據(jù)一條條地獲取并設(shè)置到具體的實(shí)體類(lèi)上,如此,該實(shí)體類(lèi)才能在接下來(lái)的程序中使用。然而問(wèn)題是,每次都要這么操作實(shí)在是太麻煩了,Spring就不應(yīng)該提供什么功能來(lái)替我們做這些事情嗎?答案當(dāng)然是有的,那就是本文的主角——RowMapper。
Spring JDBC中目前有兩個(gè)主要的RowMapper實(shí)現(xiàn),使用它們應(yīng)該能解決大部分的場(chǎng)景了。
1.1 SingleColumnRowMapper
通過(guò)名字我們就能大概了解,在查詢(xún)返回單列數(shù)據(jù)的時(shí)候,就該使用這個(gè)RowMapper,下面我們來(lái)看看具體的代碼:
@Override
public String getStudentNameById(String id) {
String sql = "select name from test_student where id = ?";
return this.jdbcTemplate.queryForObject(sql, new Object[]{id},
new SingleColumnRowMapper<>(String.class));
}
@Override
public List<String> getStudentNamesByGrade(Integer grade) {
String sql = "select name from test_student where grade = ?";
return this.jdbcTemplate.query(sql, new Object[]{grade},
new SingleColumnRowMapper<>(String.class));
}
@Test
public void getStudentNameById(){
String name = studentService.getStudentNameById("3");
assertEquals("李清照", name);
}
@Test
public void getStudentNamesByGrade(){
List<String> names = studentService.getStudentNamesByGrade(1);
assertTrue(2 == names.size());
}
1.2 BeanPropertyRowMapper
當(dāng)查詢(xún)數(shù)據(jù)庫(kù)返回的是多列數(shù)據(jù),且你需要將這些多列數(shù)據(jù)映射到某個(gè)具體的實(shí)體類(lèi)上,那么就該使用這個(gè)Row Mapper,下面是具體的使用代碼:
@Override
public Student getStudentByName2(String name) {
String sql = "select name, gender from test_student where name = ?";
return this.jdbcTemplate.queryForObject(sql, new Object[]{name},
new BeanPropertyRowMapper<>(Student.class));
}
@Override
public List<Student> getStudentsByName2(String name) {
String sql = "select name, gender from test_student where name = ?";
return this.jdbcTemplate.query(sql, new Object[]{name},
new BeanPropertyRowMapper<>(Student.class));
}
@Test
public void getStudentByName2(){
Student student = studentService.getStudentByName2("杜甫");
assertEquals("杜甫",student.getName());
assertEquals("男",student.getGender());
}
@Test
public void getStudentsByName2(){
List<Student> studentList = studentService.getStudentsByName("Jack");
assertTrue(2 == studentList.size());
}
這種使用方式有一個(gè)前提,那就是數(shù)據(jù)庫(kù)SQL查出來(lái)的數(shù)據(jù)其列名與實(shí)體類(lèi)中的屬性名是一致的,當(dāng)然個(gè)數(shù)和順序可以不一致。比如數(shù)據(jù)庫(kù)SQL查出來(lái)的姓名列叫name,那么對(duì)應(yīng)的實(shí)體類(lèi)中的姓名也必須叫name,而不能叫studentName或者其它。
二、定義自己的RowMapper
當(dāng)然,如果你SQL查詢(xún)出來(lái)的數(shù)據(jù)列名就是和實(shí)體類(lèi)的屬性名不一樣,或者想按照自己的規(guī)則來(lái)裝配實(shí)體類(lèi),那么就可以定義并使用自己的Row Mapper。
public class StudentRowMapper implements RowMapper<Student> {
@Override
public Student mapRow(ResultSet rs, int i) throws SQLException {
Student student = new Student();
student.setName(rs.getString("name"));
student.setGender(rs.getString("gender"));
student.setEmail(rs.getString("email"));
return student;
}
}
@Override
public Student getStudentByName3(String name) {
String sql = "select name, gender, email from test_student where name = ?";
return this.jdbcTemplate.queryForObject(sql, new Object[]{name}, new StudentRowMapper());
}
@Override
public List<Student> getStudentsByName3(String name) {
String sql = "select name, gender, email from test_student where name = ?";
return this.jdbcTemplate.query(sql, new Object[]{name}, new StudentRowMapper());
}
@Test
public void getStudentByName3(){
Student student = studentService.getStudentByName3("杜甫");
assertEquals("杜甫",student.getName());
assertEquals("男",student.getGender());
assertEquals("dufu@tang", student.getEmail());
}
@Test
public void getStudentsByName3(){
List<Student> studentList = studentService.getStudentsByName3("李白");
assertTrue(2 == studentList.size());
}