Spring的JdbcTemplate

一、几种数据库语言类别

  • DML(DataManipulationLanguage):数据操作语言,用来定义数据库记录(数据)
  • DCL(DataControlLanguage):数据控制语言,用来定义访问权限和安全级别;
  • DQL(DataQueryLanguage):数据查询语言,用来查询记录(数据);
  • DDL(DataDefinitionLanguage):数据定义语言,用来定义数据库对象:库、表、列等。

JdbcTemplate执行SQL语句方法的大致分类

  • execute:可以执行所有SQL语句,因为没有返回值,一般用于执行DDL语句。
  • update:用于执行INSERTUPDATEDELETE等DML语句。
  • queryForObject:用于DQL数据查询语句。

二、RowMapper

使用JDBC查询数据库得出的记录都保存在ResultSet结果集中,我们需要一条条地获取结果集中的数据并设置到具体的实体类上。RowMapper就是Spring提供的负责这些事的类。

Spring JDBC目前主要有两个主要的RowMapper实现,两者分别是:

  • SingleColumnRowMapper
  • BeanPropertyRowMapper

(一)SingleColumnRowMapper

在查询返回单列数据的时候,使用SingleColumnRowMapper

代码例子:

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

(二)BeanPropertyRowMapper

当查询数据库返回的是多列数据,且你需要将这些多列数据映射到某个具体的实体类上,使用BeanPropertyRowMapper。

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

这种使用方式有一个前提,那就是数据库SQL查出来的数据其列名与实体类中的属性名是一致的,个数和顺序可以不一致。

比如数据库SQL查出来的姓名列叫name,那么对应的实体类中的姓名也必须叫name,而不能叫studentName或者其它。

(三)自定义RowMapper

当SQL查询查出的数据列名和实体类属性名不一样时,或者想按照自己的规则来装配实体类,那么就可以定义并使用自己的RowMapper。

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());
    }
上一篇:【C++容器】key相同的键值对插入map时的覆盖问题


下一篇:Fence Painting