关于 H2

H2 数据库是一个纯 Java 实现的开源的嵌入式数据库,笔者第一次使用时还是在多年前的一个客户端项目中。

当时就觉得这个数据库很方便,如果你希望你的应用程序能"自带数据库,随处运行”,那么H2是个不错的选择。

H2 的由来

H2 的前身是 HyperSQL(HSQL),后者也是一个类似的嵌入式数据库,H2的作者 Thomas Mueller 一开始就是 HSQL的贡献者。

到后来因为一些未知的原因分成了两个项目分支,H2 大概就是第二代的意思..

有什么特性

  • 由于是Java写的,自带跨平台能力
  • 小,非常的小,完整的 Jar 包只有1-2M
  • 支持多种模式,包括内存形态、文件形态(持久化)

一般来说,使用H2 的场景大概会是:

  1. 计算资源受限,如嵌入式计算环境中,由于CPU、内存、Disk等限制,要求采用小巧的数据库存储方案;
  2. 项目预研,在项目立项之前可能无法立即采购昂贵的数据库软件,此时往往可以退而选择临时解决方案,利用JDBC协议的通用性在后期完成切换;
  3. 自动化测试,在自动化环境中可能需要大量模拟接口,包括数据存储接口,此时内存数据库是不二之选。

接下来,介绍两种使用方式

一、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项目中做单元测试。

一般,测试的流程为:

  1. 数据初始化
  2. 执行测试
  3. 销毁数据

在真实的测试代码开发中,有几类问题会造成困扰:

  1. 数据库环境的搭建比较费时费力;
  2. 数据库的数据难以保持"干净",一些垃圾数据容易影响测试的成功率

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,有兴趣的朋友可以研究对比下。

欢迎继续关注"美码师的补习系列-springboot篇" ,期待更多精彩内容-

补习系列(18)-springboot H2 迷你数据库的更多相关文章

  1. 补习系列(14)-springboot redis 整合-数据读写

    目录 一.简介 二.SpringBoot Redis 读写 A. 引入 spring-data-redis B. 序列化 C. 读写样例 三.方法级缓存 四.连接池 小结 一.简介 在 补习系列(A3 ...

  2. 补习系列(15)-springboot 分布式会话原理

    目录 一.背景 二.SpringBoot 分布式会话 三.样例程序 四.原理进阶 A. 序列化 B. 会话代理 C. 数据老化 小结 一.背景 在 补习系列(3)-springboot 几种scope ...

  3. 补习系列(17)-springboot mongodb 内嵌数据库

    目录 简介 一.使用 flapdoodle.embed.mongo A. 引入依赖 B. 准备测试类 C. 完善配置 D. 启动测试 细节 二.使用Fongo A. 引入框架 B. 准备测试类 C.业 ...

  4. 补习系列(17)-springboot mongodb 内嵌数据库【华为云技术分享】

    目录 简介 一.使用 flapdoodle.embed.mongo A. 引入依赖 B. 准备测试类 C. 完善配置 D. 启动测试 细节 二.使用Fongo A. 引入框架 B. 准备测试类 C.业 ...

  5. 补习系列(16)-springboot mongodb 数据库应用技巧

    目录 一.关于 MongoDB 二.Spring-Data-Mongo 三.整合 MongoDB CRUD A. 引入框架 B. 数据库配置 C. 数据模型 D. 数据操作 E. 自定义操作 四.高级 ...

  6. 补习系列(19)-springboot JPA + PostGreSQL

    目录 SpringBoot 整合 PostGreSQL 一.PostGreSQL简介 二.关于 SpringDataJPA 三.整合 PostGreSQL A. 依赖包 B. 配置文件 C. 模型定义 ...

  7. 补习系列(8)-springboot 单元测试之道

    目录 目标 一.About 单元测试 二.About Junit 三.SpringBoot-单元测试 项目依赖 测试样例 四.Mock测试 五.最后 目标 了解 单元测试的背景 了解如何 利用 spr ...

  8. 补习系列(6)- springboot 整合 shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  9. 补习系列(3)-springboot中的几种scope

    目标 了解HTTP 请求/响应头及常见的属性: 了解如何使用SpringBoot处理头信息 : 了解如何使用SpringBoot处理Cookie : 学会如何对 Session 进行读写: 了解如何在 ...

随机推荐

  1. SSM框架下声明式事务管理(注解配置方式)

    一.spring-mybatis.xml文件中加入事务管理配置 <?xml version="1.0" encoding="UTF-8"?> < ...

  2. SpringBoot 创建可执行Jar

    创建可执行JAR 我们也可以通过插件创建一个在生产环境中运行的可执行jar文件来完成我们的示例. 首先引入依赖: <build> <plugins> <plugin> ...

  3. Python函数化编程整理

    1.映射函数 items=[1,2,3,4,5] def inc(x): return x+1 list(map(inc,items)) [2, 3, 4, 5, 6] >>> a ...

  4. Nginx负载均衡和反向代理

    1:反向代理 代理就是中介,那有反向代理就有正向代理,两者的区别是什么嘞? 正向代理隐藏真实客户端,服务端不知道实际发起请求的客户端.,proxy和client同属一个LAN,对server透明: 反 ...

  5. 最近面了不少java开发,据此来说下我的感受:哪怕事先只准备1小时,成功概率也能大大提升

    本人最近几年一直在做java后端方面的技术面试官,而在最近两周,又密集了面试了一些java初级和高级开发的候选人,在面试过程中,我自认为比较慎重,遇到问题回答不好的候选人,我总会再三从不同方面提问,只 ...

  6. C++11 左值、右值、右值引用

    左值.右值 在C++11中所有的值必属于左值.右值两者之一,右值又可以细分为纯右值.将亡值.在C++11中可以取地址的.有名字的就是左值,反之,不能取地址的.没有名字的就是右值(将亡值或纯右值).举个 ...

  7. Python实现批量新建SecureCRT Session

    最近因为工作需要,我需要在ssh的时候保存几千台网关的session,工作量相当大(也就是ssh的时候需要记住用户名和密码,然后还要再session选项中录入enable密码,相当繁琐),而且设备的用 ...

  8. 更多细节的理解RSA算法

    一.概述 RSA算法是1977年由Ron Rivest.Adi Shamir 和 Leonard Adleman三人组在论文A Method for Obtaining Digital Signatu ...

  9. 系列博文-Three.js入门指南(张雯莉)-网格 setInterval方法 requestAnimationFrame方法 使用stat.js记录FPS

    第6章 动画 在本章之前,所有画面都是静止的,本章将介绍如果使用Three.js进行动态画面的渲染.此外,将会介绍一个Three.js作者写的另外一个库,用来观测每秒帧数(FPS). CSS3动画那么 ...

  10. latex中长公式换行,很好的办法

    今天在编辑公式时,有一个公式很长,写到一行就出去了.当时之前换行都是方程组或者在括号完之后换,都没有问题.但是今天我也换行的是在括号中间断开.这样出现问题,编辑的时候会出错误提醒.上网查了一些论坛,也 ...