Springboot 集成轻量级内存数据库H2

1. 什么是H2内存数据库

H2是一个用Java开发的嵌入式数据库,它本身是一个类库,可以直接嵌入到项目中

官网地址:H2数据库

1.1. H2用途

  • H2最大的用途在于可以同应用程序打包在一起发布,这样可以非常方便地少量结构化数据

  • 用于单元测试,启动速度块,而且可以关闭持久化功能,每一个用例执行完随机还原到初始状态

  • 作为缓存,作为NoSQL的一个补充。当某些场景下数据模型必须为关系型,可以把它当Memcached使,作为后端Mysql/Oracle的一个缓冲层,缓存一些不经常变化但需要频繁访问的数据,比如字电表、、权限表。不过这样系统架构就会比较复杂了。

1.2. H2的产品优势

  • 纯Java编写,不受平台的限制

  • 只有一个jar文件,适合作为嵌入式数据库使用

  • H2提供了一个时份翻边的web控制台用于操作和管理数据库内容

  • 功能完整,支持标准sql和jdbc

  • 支持内嵌模式、服务器模式和集群

2. Springboot集成H2

2.1. 添加H2以及相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.2. 配置H2相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
spring:
datasource:
schema: classpath:db/schema.sql #指定数据表结构文件所在目录
data: classpath:db/data.sql #指定数据文件所在目录
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test # 内存模式,数据不会持久化
#url:jdbc:h2:~/test 嵌入模式,数据文件存储在用户目录test开头的文件中
#url:jdbc:h2:tcp//localhost/〜/test 远程模式,访问远程的h2 数据库
username: sa #用户名
password: root #密码
platform: h2
h2:
console:
enabled: true
path: /h2 #H2控制台访问路径
settings:
web-allow-others: true
jpa:
hibernate:
ddl-auto: update
show-sql: true
open-in-view: true

其中在resources/db下创建表结构schema.sql

1
2
3
4
create table if not exists sys_user(
USER_ID int not null primary key auto_increment,
USER_NAME varchar(200)
);

以及数据文件 data.sql,作为初始化数据

1
2
3
4
-- 字段都是大写的
INSERT INTO SYS_USER (USER_ID, USER_NAME) VALUES (1, '小余哥');
INSERT INTO SYS_USER (USER_ID, USER_NAME) VALUES (2, '张三');
INSERT INTO SYS_USER (USER_ID, USER_NAME) VALUES (3, '李四');

2.3. 实体关联表

给User添加@Entity注解和@Table注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
@Table(name="sys_user")
@Proxy(lazy = false)
public class User {

@Id
private int userId;
/**
* userName 对应数据库 USER_NAME
* username 对应数据库 USERNAME
*/
@Column(name = "USER_NAME")
private String userName;

//----------省略getter/setter-----
}

2.4. 创建Dao继承JpaRepository

1
2
3
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
}

2.5. 访问H2控制台

启动应用程序,通过访问H2控制台连接localhost:8080/h2,进入H2控制台页面

进入控制台后,可以查看到初始化的数据表SYS_USER以及数据

2.6. 创建测试类

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
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {

@Autowired
private UserRepository userRepository;

@Test
public void save(){
User user = new User();
user.setUserName("王五");
userRepository.save(user);
//Hibernate: insert into sys_user (user_name, user_id) values (?, ?)
}

@Test
public void getOne(){
User user = userRepository.getOne(1);
System.out.println(user.toString());
//Hibernate: select user0_.user_id as user_id1_0_0_, user0_.user_name as user_nam2_0_0_ from sys_user user0_ where user0_.user_id=?
//User{userId=1, userName='小余哥'}
}

@Test
public void list(){
List<User> list = userRepository.findAll();
for (User user : list) {
System.out.println(user.toString());
}
//User{userId=1, userName='小余哥'}
//User{userId=2, userName='张三'}
//User{userId=3, userName='李四'}
}
}

3. H2数据库应用场景

3.1. 嵌入式模式(上文例子)

在嵌入式模式下,应用程序使用JDBC从同一JVM中打开数据库。这是最快也是最容易的连接方式。缺点是数据库可能只在任何时候在一个虚拟机(和类加载器)中打开。与所有模式一样,支持持久性和内存数据库。对并发打开数据库的数量或打开连接的数量没有限制

3.2. 服务器模式

当使用服务器模式(有时称为远程模式或客户机/服务器模式)时,应用程序使用 JDBC 或 ODBC API 远程打开数据库。服务器需要在同一台或另一台虚拟机上启动,或者在另一台计算机上启动。许多应用程序可以通过连接到这个服务器同时连接到同一个数据库。在内部,服务器进程在嵌入式模式下打开数据库。

服务器模式比嵌入式模式慢,因为所有数据都通过TCP/IP传输。与所有模式一样,支持持久性和内存数据库。对每个服务器并发打开的数据库数量或打开连接的数量没有限制。

3.3. 混合模式

混合模式是嵌入式和服务器模式的结合。连接到数据库的第一个应用程序在嵌入式模式下运行,但也启动服务器,以便其他应用程序(在不同进程或虚拟机中运行)可以同时访问相同的数据。本地连接的速度与数据库在嵌入式模式中的使用速度一样快,而远程连接速度稍慢。

服务器可以从应用程序内(使用服务器API)启动或停止,或自动(自动混合模式)。当使用自动混合模式时,所有想要连接到数据库的客户端(无论是本地连接还是远程连接)都可以使用完全相同的数据库URL来实现。

4. H2数据库连接格式

Connect Method URL Format and Examples
Embedded (local) connection jdbc:h2:[file:][<path>]
jdbc:h2:~/test
jdbc:h2:file:/data/sample
jdbc:h2:file:C:/data/sample (Windows only)
In-memory (private) jdbc:h2:mem:
In-memory (named) jdbc:h2:mem:
jdbc:h2:mem:test_mem
Server mode (remote connections) using TCP/IP dbc:h2:tcp://[:<port>]/[<path>]<databaseName>
jdbc:h2:tcp://localhost//test
jdbc:h2:tcp://dbserv:8084/
/sample
jdbc:h2:tcp://localhost/mem:test
Server mode (remote connections) using TLS jdbc:h2:ssl://[:<port>]/<databaseName>
jdbc:h2:ssl://localhost:8085/~/sample;
Using encrypted files jdbc:h2:;CIPHER=AES
jdbc:h2:ssl://localhost//test;CIPHER=AES
jdbc:h2:file:
/secure;CIPHER=AES
File locking methods jdbc:h2:;FILE_LOCK={FILE|SOCKET|NO}
jdbc:h2:file:~/private;CIPHER=AES;FILE_LOCK=SOCKET
Only open if it already exists jdbc:h2:;IFEXISTS=TRUE
jdbc:h2:file:~/sample;IFEXISTS=TRUE
Don’t close the database when the VM exits jdbc:h2:;DB_CLOSE_ON_EXIT=FALSE
Execute SQL on connection jdbc:h2:;INIT=RUNSCRIPT FROM ‘/create.sql’
jdbc:h2:file:
/sample;INIT=RUNSCRIPT FROM ‘/create.sql’;RUNSCRIPT FROM ‘/populate.sql’
User name and/or password jdbc:h2:[;\USER=<username>][;\PASSWORD=<value>]
jdbc:h2:file:~/sample;USER=sa;PASSWORD=123
Debug trace settings jdbc:h2:;TRACE_LEVEL_FILE=<level 0..3>
jdbc:h2:file:~/sample;TRACE_LEVEL_FILE=3
Ignore unknown settings jdbc:h2:;IGNORE_UNKNOWN_SETTINGS=TRUE
Custom file access mode jdbc:h2:;ACCESS_MODE_DATA=rws
Database in a zip file jdbc:h2:zip:<zipFileName>!/<databaseName>
jdbc:h2:zip:~/db.zip!/test
Compatibility mode jdbc:h2:;MODE=<databaseType>
jdbc:h2:~/test;MODE=MYSQL
Auto-reconnect jdbc:h2:;AUTO_RECONNECT=TRUE
jdbc:h2:tcp://localhost/~/test;AUTO_RECONNECT=TRUE
Automatic mixed mode jdbc:h2:;AUTO_SERVER=TRUE
jdbc:h2:~/test;AUTO_SERVER=TRUE
Page size jdbc:h2:;PAGE_SIZE=512
Changing other settings jdbc:h2:;=[;<setting>=<value>…]
jdbc:h2:file:~/sample;TRACE_LEVEL_SYSTEM_OUT=3