SpringBoot 整合 MyBatis-Plus 与 H2

大纲

前言

项目介绍

版本说明

框架版本描述
Spring Boot2.7.11
MyBatis-Plus3.5.3.1
H22.1.214

项目结构

代码下载

本文所需的案例代码,可以直接从 GitHub 下载对应章节 h2-springboot-mybatis-plus

项目文件

Maven 配置文件

  • pom.xml 的核心配置内容如下
1
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
<properties>
<spring-boot.version>2.7.11</spring-boot.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<h2.version>2.1.214</h2.version>
</properties>

<dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

SQL 映射文件

  • UserMapper.xml,MyBatis 的 SQL 映射文件
1
2
3
4
5
6
7
8
9
10
<?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="com.clay.h2.mapper.UserMapper">

<update id="clear">
truncate table `t_user`
</update>

</mapper>

SQL 初始化脚本文件

  • schema.sql,用于初始化数据库的表结构
1
2
3
4
5
6
7
create table if not exists `t_user` (
`id` int primary key auto_increment not null,
`username` char (50) not null,
`pwd` char(50) not null,
`create_time` datetime not null,
`update_time` datetime
);
  • data.sql,用于初始化数据库的表数据
1
insert into t_user(id, username, pwd, create_time, update_time) values (0, 'zhhangsan', '1222', {ts '2022-07-27 18:47:52.69'}, {ts '2022-07-27 18:47:52.69'});

SpringBoot 配置文件

提示

  • H2 数据库支持多种连接方式和连接设置,连接数据库的 JDBC URL 对大小写不敏感。
  • 关于 H2 的更多 JDBC URL 格式和使用示例,请看 这里 的详细介绍。

配置完整案例

1
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
server:
port: 8080

spring:
application:
name: h2-springboot-mybatis-plus
# 数据源配置
datasource:
driver-class-name: org.h2.Driver
type: com.zaxxer.hikari.HikariDataSource
# mem 表示 H2 使用内存数据库(应用重启会丢失数据)
url: jdbc:h2:mem:shopDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
username: root
password: 123456
# 数据库初始化
sql:
init:
separator: ;
encoding: UTF-8
platform: h2
mode: always
continue-on-error: false
schema-locations:
- classpath:db/schema.sql
data-locations:
- classpath:db/data.sql
# H2 的 Web 控制台
h2:
console:
enabled: true
settings:
path: /h2-console
trace: true
web-allow-others: false

# Mybatis-Plus
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
typeAliasesPackage: com.clay.*.entity
# MyBatis-Plus 配置
global-config:
db-config:
id-type: AUTO
banner: false
# MyBatis 原生配置
configuration:
map-underscore-to-camel-case: true
call-setters-on-nulls: true
jdbc-type-for-null: 'null'
# 打印 SQL 语句
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

H2 内存数据库

  • 若希望 H2 将数据库表的数据存储在内存中(应用重启后会丢失数据),可以使用以下的数据源配置信息。
1
2
3
4
5
6
7
spring:
datasource:
driver-class-name: org.h2.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:mem:shopDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
username: root
password: 123456

H2 持久化数据

  • 若希望 H2 持久化数据,可以使用以下的数据源配置信息(必须指定数据库的文件路径)。
1
2
3
4
5
6
7
spring:
datasource:
driver-class-name: org.h2.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:file:/var/database/h2/shopDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
username: root
password: 123456

H2 兼容 MySQL

  • 若希望 H2 兼容 MySQL,可以使用连接参数 MODE 来实现。
  • H2 兼容多种数据库,MODE 参数的值可以为:DB2、Derby、HSQLDB、MSSQLServer、MySQL、Oracle、PostgreSQL。
1
2
3
4
5
6
7
spring:
datasource:
driver-class-name: org.h2.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:file:/var/database/h2/shopDb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
username: root
password: 123456

H2 使用混合模式

  • 若希望 H2 使用混合模式,可以使用以下的数据源配置信息(必须指定数据库的文件路径)。
  • 值得一提的是,在默认情况下,H2 数据库同一时刻只允许一个客户端访问;设置 AUTO_SERVER=TRUE 表示启用混合模式,允许多个客户端同时连接同一个 H2 数据库,该参数不支持在内存中运行的 H2 数据库。
1
2
3
4
5
6
7
spring:
datasource:
driver-class-name: org.h2.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:/var/database/h2/shopDb;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1;AUTO_RECONNECT=TRUE
username: root
password: 123456

SpringBoot 不同版本之间的配置差异

  • 使用 SpringBoot 低版本时(如 2.3.5 版本),若希望应用在启动的时候初始化数据库,则需要使用以下的配置信息。
1
2
3
4
5
6
7
8
9
spring:
datasource:
continue-on-error: false
# 初始化模式
initialization-mode: always
# 初始化表
schema: classpath:db/schema.sql
# 初始化数据
data: classpath:db/data.sql
数据库初始化参数说明
spring.datasource.schemaDDL 表初始化语句,用于在应用程序启动时创建数据库表结构,默认加载 schema.sql 文件
spring.datasource.dataDML 数据插入语句,它用于在应用程序启动时向数据库表中插入一些初始化数据,默认加载 data.sql 文件
spring.datasource.continue-on-error指定在初始化数据库时,是否遇到错误后继续执行初始化操作。默认情况下,该属性值为 false,即遇到错误时会停止初始化操作。特别注意,如果遇到错误后继续执行,可能会导致数据库结构不完整或数据不一致,因此请谨慎使用此属性。
spring.datasource.initialization-mode数据库的初始化模式,never 表示从不初始化,embedded 表示仅初始化嵌入式的数据库,always 表示始终初始化数据库,默认值是 embedded。特别注意,如果数据库已经存在相应的表,always 模式下也会重新执行 SQL 初始化脚本,请谨慎使用此模式,否则可能会丢失数据。

配置参数说明

数据源配置参数说明
spring.datasource.url连接数据库的 URL
spring.datasource.username数据库的用户名
spring.datasource.password数据库的密码
spring.datasource.driver-class-name驱动类的全限定名
spring.datasource.type数据源类型(连接池)的全限定名

数据库初始化参数说明
spring.sql.init.separator指定 SQL 语句的断句分隔符,默认为分号 ;。如果 SQL 语句中包含存储过程或游标等语句,则需要将该属性更改为适当的分隔符,例如 $$
spring.sql.init.encoding指定 SQL 文件的编码方式,默认为 UTF-8
spring.sql.init.platform指定 SQL 方言,默认为所有方言通用
spring.sql.init.mode数据库的初始化模式,never 表示从不初始化,embedded 表示仅初始化嵌入式的数据库,always 表示始终初始化数据库,默认值是 embedded。特别注意,如果数据库已经存在相应的表,always 模式下也会重新执行 SQL 初始化脚本,请谨慎使用此模式,否则可能会丢失数据。
spring.sql.init.schema-locationsDDL 表初始化语句,用于在应用程序启动时创建数据库表结构,默认加载 schema.sql 文件
spring.sql.init.data-locationsDML 数据插入语句,它用于在应用程序启动时向数据库表中插入一些初始化数据,默认加载 data.sql 文件
spring.sql.init.continue-on-error指定在初始化数据库时,是否遇到错误后继续执行初始化操作。默认情况下,该属性值为 false,即遇到错误时会停止初始化操作。特别注意,如果遇到错误后继续执行,可能会导致数据库结构不完整或数据不一致,因此请谨慎使用此属性。

H2 数据库连接参数说明
AUTO_SERVER=TRUE启用混合模式,允许多个客户端同时连接同一个 H2 数据库,该参数不支持在内存中运行的 H2 数据库
MODE=MYSQL兼容 MySQL 数据库,该参数值可以为:DB2、Derby、HSQLDB、MSSQLServer、MySQL、Oracle、PostgreSQL
DB_CLOSE_ON_EXIT=FALSE当虚拟机退出时,并不关闭数据库
DB_CLOSE_DELAY=-1默认情况下,当最后一个连接关闭后,H2 数据库会自动关闭。为了提高数据库的性能,可以控制延迟一定的秒数后再关闭数据库。当值设置为 10,表示延迟 10 秒 再关闭数据库,当设置为 -1,表示禁用数据库自动关闭的功能。
AUTO_RECONNECT=TRUE连接丢失后自动重新连接
TRACE_LEVEL_SYSTEM_OUT=1输出跟踪日志到控制台的日志级别,取值 0 为 OFF,1 为 ERROR(默认值),2 为 INFO,3 为 DEBUG
TRACE_LEVEL_FILE=1输出跟踪日志到文件的日志级别,取值 0 为 OFF,1 为 ERROR(默认值),2 为 INFO,3 为 DEBUG

H2 的 Web 控制台参数说明
spring.h2.console.enabled启用 H2 的 Web 控制台
spring.h2.console.settings.path指定 H2 的 Web 控制台的访问路径
spring.h2.console.settings.trace开启 H2 的 Web 控制台的日志跟踪,方便开发调试
spring.h2.console.settings.web-allow-others允许 H2 的 Web 控制台的远程访问

项目代码

Util 类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {

private Integer code = 0;

private String msg;

private T data;

public Result(T data) {
this.data = data;
}

}

Entity 类代码

1
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
@Data
@ToString
@TableName("t_user")
public class User implements Serializable {

/**
* 用户主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;

/**
* 用户名称
*/
@TableField("username")
private String username;

/**
* 密码
*/
private String pwd;

/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;

/**
* 修改时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;

}

Mapper 类代码

1
2
3
4
5
6
7
8
public interface UserMapper extends BaseMapper<User> {

/**
* 清空表
*/
void clear();

}

Service 类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface UserService extends IService<User> {

/**
* 分页查询
* @return
*/
Result getByPage();

/**
* 新增记录
* @param user
* @return
*/
Result add(User user);

/**
* 清空数据
* @return
*/
Result clear();

}
1
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
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

@Override
public Result getByPage() {
Page<User> page = new Page<>(1, 10);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", "zhhangsan");
this.page(page, wrapper);
return new Result(page.getRecords());
}

@Override
@Transactional(rollbackFor = Exception.class)
public Result add(User user) {
user.setCreateTime(new Date());
return new Result(this.save(user));
}

@Override
@Transactional(rollbackFor = Exception.class)
public Result clear() {
this.baseMapper.clear();
return new Result();
}

}

Controller 类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@GetMapping("/page")
public Result getByPage() {
return userService.getByPage();
}

@PostMapping("/add")
public Result add(@RequestBody User user) {
return userService.add(user);
}

@DeleteMapping("/clear")
public Result clear() {
return userService.clear();
}

}

MyBatis-Plus 配置类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
@MapperScan("com.clay.h2.mapper")
public class MyBatisPlusConfig {

/**
* 分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}

}

项目测试

访问 H2 的 Web 控制台

启动 SpringBoot 项目后,打开浏览器访问 http://127.0.0.1:8080/h2-console,若 H2 的 Web 控制台能正常访问,且连接 H2 数据库后能看到已创建的数据库表(如下图),则说明内嵌的 H2 数据库启动成功。

H2 数据库连接

  • 在浏览器页面连接 H2 数据库时,使用的账号、密码与 JDBC URL 都是在 SpringBoot 的配置文件 application.yml 中指定的。

API 接口调用

启动 SpringBoot 项目后,使用 PostMan 等工具测试以下接口,若能得到正常的响应结果,则说明 MyBatis-Plus 成功连接并操作 H2 数据库。

API 名称 API 地址请求方法
新增用户http://127.0.0.1:8080/user/add/POST
分页查询用户http://127.0.0.1:8080/user/page/GET
删除所有用户http://127.0.0.1:8080/user/clear/DELETE

常见问题

版本兼容问题

当访问一个别人创建好的本地 H2 数据库文件,此时很有可能默认的 H2 版本不兼容导致 SpringBoot 应用启动报错(如下)

1
org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.IllegalStateException: Unable to read the page at position 70368748811782 [1.4.200/6]" [50000-200]

解决方法是弄清楚对方本地的数据库文件是 H2 哪个版本创建的,然后手动指定 Maven 配置文件中的 H2 版本号即可(如下)

1
2
3
4
5
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>

参考资料