Spring 对 JDBC API 操作数据库进行了良好的封装,通过使用 JdbcTemplate,你不必关心数据库连接创建和打开、处理异常、连接关闭等问题。这些细节都由 JdbcTemplate 底层来完成,你只需要专注于业务 SQL 语句的编写以及执行结果的处理。
在 Spring Boot 中,你可以通过spring-boot-starter-jdbc启动器快速开启和使用它。

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

1. 环境配置

在 MySQL 测试数据库创建表:

1
2
3
4
5
6
CREATE TABLE `employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(128) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk COMMENT='员工表';

编写对应的实体类:

1
2
3
4
5
6
7
8
9
10
11
public class Employee {
private Long id;
private String name;
private Integer age;
// getters and setters
}

项目配置文件信息:

# src/main/resources/application.yml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
main:
banner-mode: 'off'
datasource:
url: jdbc:mysql://127.0.0.1/test
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
tomcat:
default-auto-commit: true
logging:
level:
root: warn
org.springframework.jdbc.core.JdbcTemplate: debug

2. 保存操作

向数据库插入一条记录:

1
2
3
4
public int save(Employee employee) {
return jdbcTemplate.update("INSERT INTO EMPLOYEE(NAME, AGE) VALUE (?, ?)",
employee.getName(), employee.getAge());
}

如果表的主键字段是自动递增的,可以使用GeneratedKeyHolder来接收 SQL 执行完成之后插入数据库的记录的主键的值:

1
2
3
4
5
6
7
8
9
10
11
12
public Employee save(Employee employee) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(con -> {
PreparedStatement ps = con.prepareStatement("INSERT INTO EMPLOYEE(NAME, AGE) VALUE (?, ?)",
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, employee.getName());
ps.setInt(2, employee.getAge());
return ps;
}, keyHolder);
employee.setId(keyHolder.getKey().longValue());
return employee;
}

3. 查询操作

查询某个字段信息:

1
2
3
4
public String findNameById(Long id) {
return jdbcTemplate.queryForObject("SELECT NAME FROM EMPLOYEE WHERE ID = ?",
new Object[]{id}, String.class);
}

查询一条完整的记录:

1
2
3
4
5
6
7
8
9
10
public Employee findById(Long id) {
return jdbcTemplate.queryForObject("SELECT * FROM EMPLOYEE WHERE ID = ?",
new Object[]{id}, (rs, rowNum) -> {
Employee employee = new Employee();
employee.setId(rs.getLong("id"));
employee.setAge(rs.getInt("age"));
employee.setName(rs.getString("name"));
return employee;
});
}

查询所有的记录:

1
2
3
4
5
6
7
8
9
10
public List<Employee> findAll() {
return jdbcTemplate.query("SELECT * FROM EMPLOYEE",
(rs, rowNum) -> {
Employee employee = new Employee();
employee.setId(rs.getLong("id"));
employee.setAge(rs.getInt("age"));
employee.setName(rs.getString("name"));
return employee;
});
}

4. 更新操作

更新数据库中的一条记录:

1
2
3
4
public int update(Employee employee) {
return jdbcTemplate.update("UPDATE EMPLOYEE SET NAME = ?, AGE = ? WHERE ID = ?",
employee.getName(), employee.getAge(), employee.getId());
}

批量更新记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public int[] batchUpdate(List<Employee> employees) {
return jdbcTemplate.batchUpdate("UPDATE EMPLOYEE SET NAME = ?, AGE = ? WHERE ID = ?",
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Employee employee = employees.get(i);
ps.setString(1, employee.getName());
ps.setInt(2, employee.getAge());
ps.setLong(3, employee.getId());
}
@Override
public int getBatchSize() {
return employees.size();
}
});
}

5. 删除操作

删除一条记录:

1
2
3
public int delete(Long id) {
return jdbcTemplate.update("DELETE FROM EMPLOYEE WHERE ID = ?", id);
}

示例项目开发环境:Java-8、Maven-3、IntelliJ IDEA-2017、Spring Boot-1.5.2.RELEASE
完整示例项目链接:spring-boot-jdbc-sample
参考文档文献链接:relational-data-access