使用JDBC
# 5.1 Spring Boot 集成 JdbcTemplate
原生的 jdbc 操作并不友好:需要自己加载驱动、创建连接、写数据库查询/新增/修改/删除的 SQL(或调用存储过程)、自己控制事务、完成从数据库返回的 ResultSet(java.sql.ResultSet)中取数(字段值)并且再把这些数存放到对象中。整个过程比较复杂,经常重复,并且没有什么技术含量。
针对这种情况,各种 ORM( Object Relational Mapping, 对象关系映射)技术应运而生,解决关系数据库到 java 对象的匹配问题。在这个领域中,经常使用到的有 JPA、Hibernate、MyBatis 等 ORM 框架。
当然,在大部分项目情况下,我们都会直接使用更加强大的持久化框架来访问数据库,比如 MyBatis、Hibernate 或者 Spring Data JPA,但有的时候在项目中也会直接用到原生 jdbc 来操作数据库。我现在能够想到的唯一原因,就是原生 jdbc 直接、小巧、不引入第三方库。
但是,在 Spring 应用中,直接使用 jdbc 方式已经几乎见不到了。为了方便,Spring 对数据库的操作在 jdbc 上面做了更深层次的封装(也是非常薄的一层封装)。
Spring 封装提供的 JdbcTemplate 就是一个操作数据库的便捷工具。我们可以借助 JdbcTemplate 来执行所有数据库操作,例如插入,更新,删除和从数据库中检索数据,并且有效避免直接使用 jdbc 带来的繁琐编码工作。
JdbcTemplate 主要提供以下五种类型的方法:
- execute 方法:可以用于执行任何 SQL 语句,一般用于执行 DDL 语句。
- update、batchUpdate 方法:用于执行新增、修改、删除等语句。
- query 方法及 queryForXXX 方法:用于执行查询相关的语句。
- call 方法:用于执行数据库存储过程和函数相关的语句。
下面我们在 Spring Boot 应用中引入 JdbcTemplate 方式操作数据,看看如何将 JdbcTemplate 技术集成到 Spring Boot 项目中去。
# 5.1.1 新建项目
使用 Spring Starter 工具新建 Spring Boot 项目。
注意要选中 JDBC API、MySQL Driver 和 Spring Web 的依赖。
JDBC API 依赖对应的 starter 是:
spring-boot-starter-jdbc
。
项目的pom文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>jdbc-template</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jdbc-template</name>
<description>JdbcTemplate Example.</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
项目的配置文件application.yml
中配置数据库连接信息。
# mysql数据源配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/spring_boot_course?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
2
3
4
5
6
7
需要注意的是:在我们的练习环境中使用的是MySQL 5.7数据库,Spring Boot使用当前的jdbc驱动(8.0.18)application.yml配置需要注意如下两点:
- url需要设置时区参数,例如
jdbc:mysql://localhost:3306/spring_boot_course?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
;- jdbc驱动,需要使用
com.mysql.cj.jdbc.Driver
。
# 5.1.2 新建 Entity 类
实体类,一般对应了数据库中的表,其中的每一个属性,对应了表中的一个字段。
package com.example.jdbctemplate.entity;
public class User {
private Integer id;
private String userName;
private String passWord;
private String realName;
(省略getter、setter)
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", passWord='" + passWord + '\'' +
", realName='" + realName + '\'' +
'}';
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
对应表 user 的 MySQL DDL 如下:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`userName` varchar(32) NOT NULL,
`passWord` varchar(50) NOT NULL,
`realName` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
2
3
4
5
6
7
8
插入1条数据,供测试:
INSERT INTO `user` VALUES ('1', 'Kevin', '123456', '长的帅');
# 5.1.3 新建 DAO 类
DAO 类是通过 JdbcTemplate 存取数据的关键,并且通过@Repository
注解将其纳入 Spring 容器管理,供其他 Spring 组件(bean)使用,一般都是注入到 Service 类中。
package com.example.jdbctemplate.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.example.jdbctemplate.entity.User;
@Repository
public class UserDAO {
@Autowired
JdbcTemplate jdbcTemplate;
public User getUser(int id) {
String sql = "select * from user where id=" + id;
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
注意上面代码中的第 13-14 行,其中直接注入了 JdbcTemplate 对象,供操作 SQL 用。
第 17-18 行,就是使用 JdbcTemplate 对象完成了一次查询,并且将数据库查询结果(一行数据)封装(BeanPropertyRowMapper)到了一个对象(实体类 User 对象)中。
JdbcTemplate对象是从哪里来的?那就是 Spring Boot Starter(启动器)的魔法了。
在本项目中,
spring-boot-starter-jdbc
自动在 Spring 容器中注册了 JdbcTemplate 对象。
# 5.1.4 新建 Service 类
服务类中注入 DAO 类,在向外提供的服务中需要用数据库操作时,调用 DAO 对象的对应方法,即可和数据库交互。
package com.example.jdbctemplate.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.jdbctemplate.dao.UserDAO;
import com.example.jdbctemplate.entity.User;
@Service
public class UserService {
@Autowired
UserDAO userDAO;
public User getUser(int id) {
return userDAO.getUser(id);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 5.1.5 新建 Controller 类
新建一个控制器类,在接收到用户请求/user/get/1
时通过 Service 对象中的 DAO 对象对应方法访问数据库中 id=1 的这条记录,并通过 ResponseBody 返回。
package com.example.jdbctemplate.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.jdbctemplate.service.UserService;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("get/{id}")
public String getUser(@PathVariable int id) {
return userService.getUser(id).toString();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 5.2.6 运行验证
运行该项目的启动类JdbcTemplateApplication
,在浏览器中访问http://localhost:8080/user/get/1 (opens new window),验证是否可以正确的查询到数据库中的记录。
以上就是如何在 Spring Boot 中集成JdbcTemplate
,使用最简单最原始的 SQL 与数据库交互的示例。
在大多数情况下,我们都会选择一些 ORM 技术来与数据库进行交互,下一小节,我们会介绍 MyBatis 这个广受欢迎的 ORM 框架。
本小节示例项目代码:
https://github.com/gyzhang/SpringBootCourseCode/tree/master/spring-boot-jdbc (opens new window)