我们在 Spring Boot 整合 Mybatis 中提到了 myabtis-spring-boot-starter 中引入了 spring-boot-starter-jdbc 依赖。而使用 JdbcTemplate 我们只需要在项目中引入 spring-boot-starter-jdbc 就可以使用了。

1. 添加依赖


在项目中我们依然使用 Druid 连接池,故添加 Druid 相关依赖:

<!-- jdbc -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>${druid.version}</version>
</dependency>

2. 配置文件


与配置 Mybatis 不同的是,在 application.yml 中不需要对 mybatis 进行配置,其他的完全一致,这里去除了 druid 的监控相关功能,只配置数据连接。

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      ## 数据库连接
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: demo
      password: demo

      ## 连接池配置
      ## 初始化大小
      initial-size: 5
      ## 最小连接数
      min-idle: 1
      ## 最大连接数
      max-active: 20
      ## 连接等待超时时间 30s
      max-wait: 30000
      ## 检测可以关闭的空闲连接间隔时间 60s
      time-between-eviction-runs-millis: 60000
      ## 连接池中连接的最小生存时间 30s
      min-evictable-idle-time-millis: 30000
      validation-query: SELECT '1'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      ## 打开 PSCache,指定每个连接的 PSCache 大小
      pool-prepared-statements: true
      max-open-prepared-statements: 20
      max-pool-prepared-statement-per-connection-size: 20

3. 编写 Dao

基于 SOA 模型架构,首先提供一个 Dao 接口

public interface IStudentDao {

    /**
     * 新增学生信息
     * @param student 学生信息
     * @return
     */
    int add(Student student);

    /**
     * 删除学生信息
     * @param studentId 学生id
     * @return
     */
    int delete(String studentId);

    /**
     * 更新学生信息
     * @param student 学生信息
     * @return
     */
    int update(Student student);

    /**
     * 查询学生信息
     * @param studentId 学生id
     * @return
     */
    Student queryById(String studentId);

    /**
     * 查询所有学生信息的学生类列表
     * @return
     */
    List<Student> queryList();
}

Dao 接口实现

@Repository
public class StudentDaoImpl implements IStudentDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int add(Student student) {
        String sql = "insert into tb_student (S_ID, S_NAME, SEX) values (?, ?, ?)";
        Object[] args = {student.getStudentId(), student.getName(), student.getSex()};
        int[] argTypes = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR};
        return jdbcTemplate.update(sql, args, argTypes);

//        String sql = "insert into tb_student(S_ID,S_NAME,SEX) values(:studentId,:name,:sex)";
//        NamedParameterJdbcTemplate namedParameterJdbcTemplate =
//                new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
//        return namedParameterJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(student));
    }

    @Override
    public int delete(String studentId) {
        String sql = "delete from tb_student where S_ID = ?";
        Object[] args = {studentId};
        int[] argTypes = {Types.VARCHAR};
        return jdbcTemplate.update(sql, args, argTypes);
    }

    @Override
    public int update(Student student) {
        String sql = "update tb_student set S_NAME = ?, SEX = ? where S_ID = ?";
        Object[] args = {student.getName(), student.getSex(), student.getStudentId()};
        int[] argTypes = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR};
        return jdbcTemplate.update(sql, args, argTypes);
    }

    @Override
    public Student queryById(String studentId) {
        String sql = "select * from tb_student where S_ID = ?";
        Object[] args = {studentId};
        int[] argTypes = {Types.VARCHAR};
        return jdbcTemplate.queryForObject(sql, args, argTypes, new StudentMapper());
    }

    @Override
    public List<Student> queryList() {
        String sql = "select * from tb_student";
        return jdbcTemplate.query(sql, new StudentMapper());
    }
}

可见使用 JdbcTemplate 与我们最开始接触的 JDBC 的使用方法一模一样:编写原生 sql 语句,通过 JdbcTemplate 执行 sql 语句返回结果。

在插入数据的时候可以用两种方式:

  • JdbcTemplateupdate 方法。
  • NamedParameterJdbcTemplateupdate 方法。

这两种方式的主要区别是:NamedParameterJdbcTemplate 传入的 sql 语句中不使用 ?占位符,直接使用实体类的字段名称。

所以在插入的字段较多时候,使用 NamedParameterJdbcTemplateupdate 方法可以起到缩减代码量的效果。


在执行查询语句后,需要将查询结果封装为对应的实体类之后再返回给调用者。作为 Spring 提供的 ORM 持久化技术之一, JdbcTemplate 当然也能通过添加映射关系来获取指定的实体类对象。

RowMapper 接口源码

@FunctionalInterface
public interface RowMapper<T> {

	/**
	 * Implementations must implement this method to map each row of data
	 * in the ResultSet. This method should not call {@code next()} on
	 * the ResultSet; it is only supposed to map values of the current row.
	 * @param rs the ResultSet to map (pre-initialized for the current row)
	 * @param rowNum the number of the current row
	 * @return the result object for the current row (may be {@code null})
	 * @throws SQLException if a SQLException is encountered getting
	 * column values (that is, there's no need to catch SQLException)
	 */
	@Nullable
	T mapRow(ResultSet rs, int rowNum) throws SQLException;

}

该接口为配置映射关系的关键接口,我们通过实现 mapRow 方法即可配置映射关系:

public class StudentMapper implements RowMapper<Student> {
    @Override
    public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
        Student student = new Student();
        student.setStudentId(rs.getString("S_ID"));
        student.setName(rs.getString("S_NAME"));
        student.setSex(rs.getString("SEX"));

        return student;
    }
}

4. 测试


新增数据

@Test
public void addStudent() {
    Student student = new Student();
    student.setStudentId("004");
    student.setName("Mark");
    student.setSex("M");
    int count = studentService.add(student);
    System.out.println(count > 0 ? "add success" : "add fail");
}

通过 ID 查询

@Test
public void queryStudent() {
    Student student = studentService.queryById("004");
    System.out.println(student);
}
Student{studentId='004', name='Mark', sex='M'}

更新数据

@Test
public void updateStudent() {
    Student student = studentService.queryById("004");
    student.setName("Jane");
    student.setSex("F");
    int update = studentService.update(student);
    System.out.println(update > 0 ? "update success" : "update fail");
}

查询列表:

@Test
public void delete() {
    int delete = studentService.delete("004");
    System.out.println(delete > 0 ? "delete success" : "delete fail");
}
Student{studentId='001', name='Jack', sex='M '}
Student{studentId='002', name='Jim', sex='M '}
Student{studentId='003', name='Julia', sex='F '}
Student{studentId='004', name='Jane', sex='F'}

源码地址:https://github.com/NekoChips/SpringDemo/tree/master/04.springboot-JdbcTemplate


关于作者:NekoChips
本文地址:https://chenyangjie.com.cn/articles/2020/04/25/1587791589614.html
版权声明:本篇所有文章仅用于学习和技术交流,本作品采用 BY-NC-SA 4.0 许可协议,如需转载请注明出处!
许可协议:知识共享许可协议