Spring Boot集成SQL数据库1
从银行的交易数据到打车订单,衣食住行,都离不开数据库的存储。
在接下来的两个小节中,我们将通过3种不同的技术,在Spring Boot中集成MySQL数据库。
-
JDBC
-
MyBatis
-
JPA (Hibernate)
本节的前半部分,我们将通过Docker快速搭建MySQL的环境,随后介绍JDBC的集成方式。
搭建MySQL实验环境
本书的重点是讨论微服务实战,我们直接使用Docker的方式,快速搭建实验环境。
如果你想部署在生产环境,请参考官方部署文档。
首先,请确认已经成功安装了Docker:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
若尚未安装Docker,可以参考[官方文档](Install Docker Engine | Docker Documentation)。
MySQL的Docker运行脚本如下:
#!/bin/bash
NAME="mysql"
PUID="1000"
PGID="1000"
VOLUME="$HOME/docker_data/mysql"
MYSQL_ROOT_PASS="123456"
mkdir -p $VOLUME
docker ps -q -a --filter "name=$NAME" | xargs -I {} docker rm -f {}
docker run \
--hostname $NAME \
--name $NAME \
--volume "$VOLUME":/var/lib/mysql \
--env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASS \
--env PUID=$PUID \
--env PGID=$PGID \
-p 3306:3306 \
--detach \
--restart always \
mysql:8.0
如脚本所述:
-
使用官方的8.0镜像启动Docker
-
退出后自动重启
-
暴露3306端口到本机
-
设置Volume盘到~/docker_data/mysql路径下
-
root密码123456(请务必更改为安全密码)
执行后的效果:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
feb2838197a6 mysql:8.0 "docker-entrypoint.s…" 46 hours ago Up 7 hours 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
启动成功后,我们尝试连接数据库,新建库并授权给用户:
mysql -h 127.0.0.1 -u root -p
> CREATE DATABASE homs_demo;
> CREATE USER 'HomsDemo'@'%' identified by '123456';
> GRANT ALL PRIVILEGES ON homs_demo.* TO 'HomsDemo'@'%';
尝试用新用户登录:
mysql -h 127.0.0.1 -u HomsDemo -p homs_demo
若能成功登录,我们创建本书实验所需的表:
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这里我们创建了表users,有两个列:id和name。
温馨提示:我们使用utf8mb4字符集,如果用utf8是会有坑,可以参考这篇文章。强烈推荐你对所有的数据表,都设置为utf8mb4。
Spring Boot 集成 JDBC操作MySQL
我们先通过集成jdbc的方式操作MySQL数据库。
首先在server项目的build.gradle中添加依赖
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'mysql:mysql-connector-java:8.0.20'
上述依赖中:
-
spring-boot-starter-jdbc是集成jdbc的starter依赖包
-
mysql-connector-java是集成MySQL的驱动
接着,我们配置下数据源:
spring.datasource:
url: jdbc:mysql://127.0.0.1:3306/homs_demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: HomsDemo
password: 123456
hikari:
minimumIdle: 10
maximumPoolSize: 100
上述配置分为两部分:
-
spring.datasource.url / username / password定义了MySQL的访问链接
-
hikari是数据库连接池的配置。
Hikari是Spring Boot 2默认的链接池,官方性能评测优秀。这里我们配置了minimumIdle(最小连接数)和maximumPoolSize(最大连接数)两个选项。更多配置参数可以参考[官方文档](GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.)。
经过上述的组合配置后,对应DataSource对应的Configuration会自动激活,并注册一系列的关联Bean。
下面让我们使用它访问MySQL数据库:
@Repository
public class UserRepository1Impl implements UserRepository {
@Autowired
protected NamedParameterJdbcTemplate db;
private static RowMapper<User> ROW_MAPPER = new BeanPropertyRowMapper<>(User.class);
@Override
public Optional<Long> create(User user) {
String sql = "INSERT INTO `users`(`name`) VALUES(:name)";
SqlParameterSource param = new MapSqlParameterSource("name", user.getName());
KeyHolder holder = new GeneratedKeyHolder();
if (db.update(sql, param, holder) > 0) {
return Optional.ofNullable(holder.getKey().longValue());
} else {
return Optional.empty();
}
}
@Override
public Optional<User> getUser(long id) {
String sql = "SELECT * FROM `users` WHERE `id` = :id";
SqlParameterSource param = new MapSqlParameterSource("id", id);
try {
return Optional.ofNullable(db.queryForObject(sql, param, ROW_MAPPER));
} catch (EmptyResultDataAccessException e) {
return Optional.empty();
}
}
@Override
public Optional<User> getUserByName(String name) {
String sql = "SELECT * FROM `users` WHERE `name` = :name";
SqlParameterSource param = new MapSqlParameterSource("name", name);
try {
return Optional.ofNullable(db.queryForObject(sql, param, ROW_MAPPER));
} catch (EmptyResultDataAccessException e) {
return Optional.empty();
}
}
}
在上面的代码中,我们自动装配了"NamedParameterJdbcTemplate",然后用它访问MySQL数据库:
-
读请求使用db.query,配合RowMapper做类型转化
-
写请求使用db.update,配合KeyHolder获取自增主键
使用JDBC访问MySQL的方式,优点和缺点是完全一样的:使用显示的SQL语句操作数据库。
优点:直接、方便代码Review和性能检查
缺点:SQL编写过程繁琐、易错,特别是对于CRUD请求,效率较低