关于 H2
H2 数据库是一个纯 Java 实现的开源的嵌入式数据库, 笔者第一次使用时还是在多年前的一个客户端项目中.
当时就觉得这个数据库很方便, 如果你希望你的应用程序能 "自带数据库, 随处运行", 那么 H2 是个不错的选择.
H2 的由来
H2 的前身是 HyperSQL(HSQL), 后者也是一个类似的嵌入式数据库, H2 的作者 Thomas Mueller 一开始就是 HSQL 的贡献者.
到后来因为一些未知的原因分成了两个项目分支, H2 大概就是第二代的意思..
有什么特性
由于是 Java 写的, 自带跨平台能力
小, 非常的小, 完整的 Jar 包只有 1-2M
支持多种模式, 包括内存形态, 文件形态 (持久化)
一般来说, 使用 H2 的场景大概会是:
计算资源受限, 如嵌入式计算环境中, 由于 CPU, 内存, Disk 等限制, 要求采用小巧的数据库存储方案;
项目预研, 在项目立项之前可能无法立即采购昂贵的数据库软件, 此时往往可以退而选择临时解决方案, 利用 JDBC 协议的通用性在后期完成切换;
自动化测试, 在自动化环境中可能需要大量模拟接口, 包括数据存储接口, 此时内存数据库是不二之选.
接下来, 介绍两种使用方式
一, H2 用作本地数据库
1. 引入依赖:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- <version>${spring-boot.version}</version>
- </dependency>
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- <version>1.4.196</version>
- </dependency>
2. 配置文件
编辑 application.properties:
- ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
- spring.datasource.url=jdbc:h2:file:D:/temp/h2
- spring.datasource.username=
- spring.datasource.password=
- # The SQL dialect makes Hibernate generate better SQL for the chosen database
- spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
- # Hibernate ddl auto (create, create-drop, validate, update)
- spring.jpa.hibernate.ddl-auto = update
其中 jdbc:h2:file:D:/temp/h2 将指示 H2 启用本地文件模式, 数据库文件将写入 D:/temp/h2 这个目录.
3. 样例数据
LogRecord.java
- @Entity
- @Table(name="log_record")
- public class LogRecord {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO )
- private Long id;
- private String level;
- private String message;
- private Date createTime;
LogRepository.java
- @Repository
- public interface LogRecordRepository extends JpaRepository<LogRecord, Long> {
- }
LogRecordInitializer.java
- @Service
- public class LogRecordInitializer {
- @Autowired
- private LogRecordRepository logRecordRepository;
- private static final Logger logger = LoggerFactory.getLogger(LogRecordInitializer.class);
- @PostConstruct
- void initData(){
- if(logRecordRepository.count()> 0){
- List<LogRecord> logRecords = logRecordRepository.findAll();
- logger.info("read records: {}", JsonUtil.toPrettyJson(logRecords));
- return;
- }
- for(int i=0; i<100; i++){
- LogRecord record = new LogRecord();
- record.setLevel("info");
- record.setMessage("Heartbeat message" + UUID.randomUUID().toString());
- record.setCreateTime(new Date());
- logRecordRepository.save(record);
- logger.info("save record -" + record.getMessage());
- }
- }
- }
实现的逻辑大致是, 第一次启动时写入 100 条数据, 后面每次启动将数据读取出来并打印到日志.
执行 SpringBoot 启动程序, 发现目录中生成了 h2.mv.db 文件, 说明写入成功!
二, H2 用于单元测试
H2 数据库的典型应用是 在 web 项目中做单元测试.
一般, 测试的流程为:
数据初始化
执行测试
销毁数据
在真实的测试代码开发中, 有几类问题会造成困扰:
数据库环境的搭建比较费时费力;
数据库的数据难以保持 "干净", 一些垃圾数据容易影响测试的成功率
H2 作为内存数据库使用则能解决这些问题, 本身作为内置数据库并不需要额外的看护成本,
而且在程序退出时, 所有数据都能保证完全清除.
1. 依赖包
- <!-- springboot test -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <version>${spring-boot.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- <version>1.4.196</version>
- <scope>test</scope>
- </dependency>
2. 测试配置
编辑 src/test/resources/application.properties
- # 数据源连接
- spring.datasource.url=jdbc:h2:mem:test
- # DDL 脚本
- spring.datasource.schema=classpath:script/test-schema.sql
- # DML 脚本
- spring.datasource.data=classpath:script/test-data.sql
- spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
- spring.jpa.hibernate.ddl-auto = update
3. 测试代码
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = BootJpa.class)
- public class CityViewRepositoryTest {
- @Autowired
- private CityViewRepository cityViewRepository;
- @Test
- public void testGetAll(){
- List<CityView> views = cityViewRepository.findAll();
- System.out.println(JsonUtil.toPrettyJson(views));
- }
- }
小结
本篇介绍了 H2 数据库常用的两种使用场景. 尽管此前也写过关于 H2 做单元测试的文章,
但除此之外, 其作为嵌入式数据库也是不错的选择, 从行业趋势来看, 终端计算对于嵌入式 DB 的需求会越来越多, 后面也是比较看好的.
与 H2 类似的数据库还有 HSQL,Derby, 有兴趣的朋友可以研究对比下.
来源: https://yq.aliyun.com/articles/693719