这篇文章主要学习关系型数据库主流的技术栈,我们使用 Docker
快速搭建一个 MySQL
数据库学习环境,通过 MySQL 官方提供的 Workbench
可视化工具的去操作 MySQL (类似要付费的 Navicat
)。
在 Spring Boot 中,我们借助阿里开源的优秀的数据库连接池 Druid
,结合业内优秀的持久层框架 MyBatis
,从零一步步实现一个比较全的 Demo。
本文尽量从零去理解、去学习如何使用 Druid 和 MyBatis,有广度,无深入
,此为第一篇,后续会写包括如使用 MyBatis 代码生成器 MyBatis Generator
以及 Druid、MyBatis 的具体用法,慢慢深入。
名词 | 释义 |
---|---|
DBMS | 数据库管理系统,粗分为 RDBMS 和 No SQL 两种类型数据库,还有一种介于两者之间的 New SQL(分布式关系型数据库) |
ODBC | ODBC 是数据库系统访问 API 接口,由微软倡导。该 API 独立于任何一种 DBMS 或操作系统;尽管它的实现使用 C,但 ODBC API 与语言无关。ODBC API 基于 Open Group 和 ISO/IEC 的 CLI 规范,ODBC 3.x 完全实现了这两个规范。 |
JDBC | Java Database Connectivity,Java 层 数据库连接统一标准接口,跟 ODBC 作用类似。早期为了访问各种数据库,有 JDBC-ODBC 桥,将 JDBC-API 映射为 ODBC-API,JDK8 已移除。 |
ORM | Object Relational Mapping,对象关系映射,字面通俗理解就是将数据表关系和记录映射成 Java 层类及对象 |
JPA | Java Persistence API,Java 持久化规范,是 ORM 框架的标准,是为了更好支持面向对象操作 |
Hibernate | 一个实现了 ORM 规范(JPA)的持久层框架,而 JPA 对数据连接操作还是使用 JDBC |
Spring Data JPA | 底层还是用的实现了 JPA 的 Hibernate,更强化,更易用 |
MyBatis | 也是一个持久层框架,支持自定义 SQL、存储过程以及高级映射。 |
DBCP | DataBase connection pool,数据库连接池,是 Apache 上的一个 Java 连接池项目 |
Druid | Druid 是阿里巴巴开源的 Java 语言中优秀的数据库连接池。Druid 能够提供强大的监控和扩展功能 |
Druid,数据库连接池,同时加入了日志监控,可以很好的监控池连接和 SQL 的执行情况
MyBatis3
*.xml
语句映射--> 映射 Java 接口
<mybatis:scan/>
元素@Mapper
(推荐)@MapperScan
(推荐)# docker 对于不存在的镜像会先自动下载,然后再启动容器实例
$ docker run --name test-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7.32
# 进入容器进行 bash 操作
$ docker exec -it test-mysql bash
$ mysql -u root -p123456
mysql> create database db_example; -- 创建数据库 db_example
mysql> create user 'springuser'@'%' identified by 'ThePassword'; -- 创建新用户
mysql> grant all on db_example.* to 'springuser'@'%'; -- 向新用户授予新创建数据库的所有权限
mysql> revoke all on db_example.* from 'springuser'@'%'; -- 取消授权用户的所有权限
mysql> grant select, insert, delete, update on db_example.* to 'springuser'@'%'; -- 授予用户所需的最低权限(用于生产环境中)
# 停止容器实例运行
$ docker container stop test-mysql
# 启动已停止运行的容器实例
$ docker container start test-mysql
对镜像和容器的管理还可以借助 Docker Desktop
进行操作,方便直观。创建数据库也可以通过 MySQL Workbench
实现。
<!-- jdbc-mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
springboot
数据库)这里我们演示通过在 Spring Boot 项目中使用 SQL 脚本实现数据库表初始化:
main/java/resources
目录下创建 schema-mysql.sql
和 data-mysql.sql
main/java/resources
目录下的 application.yaml
中配置数据库连接和指定 SQL 脚本信息# 开启调试,可以输出 schema 的创建过程
debug: true
spring:
jpa:
# 禁用 JPA 初始化数据库方式
generate-ddl: false
show-sql: true
# 禁用 Hibernate 初始化数据库方式
hibernate:
ddl-auto: none
datasource:
type: com.alibaba.druid.pool.DruidDataSource
# 指定特定平台
#platform: MYSQL
url: jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: admin
driver-class-name: com.mysql.cj.jdbc.Driver
# ------------------------
# 数据库初始化配置
# ------------------------
schema: classpath:schema-mysql.sql
data: classpath:data-mysql.sql
# always: 总是会执行初始化操作;embedded: 仅初始化嵌入式数据源(如H2,HSQL,Derby); never: 不做初始化操作
initialization-mode: always
DO 类的编写主要是类中成员属性与数据表保持一致,一般数据库表中我们常用 xx_yy
中间加下划杠命名列字段,而 Java 中都是驼峰法,这个是可以通过 MyBatis 配置去做到转换或者别名的。这里不用考虑数据库表字段和 DO 类属性的大小写问题,自动映射会忽略大小写。
select user_id as 'id' from tbl_user
<result property="id" column="user_id"/>
map-underscore-to-camel-case: true
DO 类 User.java 示例:
import lombok.Data;
@Data
public class User {
private Long id;
private String userName;
private Integer age;
}
这里用了 lombok 的 @Data
注解,等效 @ToString
、@EqualsAndHashCode
、@Getter
、@Setter
、@RequiredArgsConstructor
这些注解作用,即生成属性的 get/set 方法、toString 方法、equals(Object other)、hashCode()及所有属性为形参的构造方法。
Mapper 接口类 UserMapper.java 示例:
public interface UserMapper {
List<User> getUsers();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.xiaobaiai.demos.mapper.manual.UserMapper">
<select id="getUsers" resultType="User">
select id, username, age from tbl_user
</select>
</mapper>
映射文件很短,这里不展示复杂的对象关系映射,更多复杂操作可以参见官方网站 https://mybatis.org/mybatis-3/zh/sqlmap-xml.html 。<select
标记中的 id
就是我们映射接口类中方法名,返回结果就是 User
DO 类型。这里的 namespace
是命名空间,跟 C++
编程语言中命名空间作用类似,也是规范映射接口类的方法作用范围,不过这里同时也是接口绑定的实现声明。
上面已经将对象关系映射都写好了,在 Spring Boot 中想要实例化我们的映射接口,还需要配置映射器发现,另外让程序找到映射文件,也需要配置 MyBatis。映射器的发现在综述中概括提到了几种方式,这里我们推荐使用注解的方式,好用又简单。
@Mapper
:作用于映射接口类 UserMapper.java ,即可实现映射器发现;如果有多个映射接口类,则每个都需要加上。@MapperScan
: 指定需要扫描的映射接口包,示例,比如 UserMapper.java 存放于 net.xiaobaiai.demos.mapper.manual
包下:@SpringBootApplication
@MapperScan("net.xiaobaiai.demos.mapper.manual")
public class DemoMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(DemoMybatisApplication.class, args);
}
}
@MapperScan
可以使用通配符 *
,匹配多个包,如 net.xiaobaiai.demos.mapper.*
,也可以设置多个包,如 @MapperScan({"com.xx.x", "com.xx.y"})
。
MyBatis 需要配置最基本的一些配置,才能让整个对象关系映射起作用:
mybatis:
# DO 类 User.java 别名包路径
type-aliases-package: net.xiaobaiai.demos.entity.manual
# 配置映射文件路径
mapper-locations: classpath:mapper/**/*.xml
configuration:
# 配置自动转换策略
map-underscore-to-camel-case: true
最后我们配置数据库连接池 Druid:
# ------------------------
# druid 通用配置
# ------------------------
druid:
# 初始化建立物理连接的个数
initial-size: 5
# 最大连接池数
max-active: 30
# 最小连接池数
min-idle: 5
# 获取连接时最大等待时间(ms)
max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 连接保持空闲而不被驱逐的最小时间
min-evictable-idle-time-millis: 300000
# 申请连接/归还连接时相关检测开关
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 设置是否缓存 preparedStatement,官方建议mysql下关闭,oracle下开启
pool-prepared-statements: false
# 大于0,会自动触发pool-prepared-statements为true,建议设置较大,如100
max-pool-prepared-statement-per-connection-size: -1
# 配置监控统计拦截插件,如stat,log4j,wall
filters: stat,wall
最后想要测试或者编写业务逻辑,比如调用 Mapper 接口方法,可以继续编写 Service 和 Controller,这里就不展开了,重点是我们弄清楚了 MyBatis 的配置和使用起来,以及如何查找相关文档进一步在工作中使用。
从零学习 Spring Boot,本文从比较广的角度去了解了 Spring 数据库相关的概念,入门数据库连接池 Druid 以及数据库持久层框架 MyBatis。参考资料所列出的链接可以进一步让我们学习 MyBatis 和 Druid,加深我们的理解。最后,Demo 工程开源在我的 Github 上。