补习系列(18)-springboot H2 迷你数据库
关于 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,有兴趣的朋友可以研究对比下。
欢迎继续关注"美码师的补习系列-springboot篇" ,期待更多精彩内容-
补习系列(18)-springboot H2 迷你数据库的更多相关文章
- 补习系列(14)-springboot redis 整合-数据读写
目录 一.简介 二.SpringBoot Redis 读写 A. 引入 spring-data-redis B. 序列化 C. 读写样例 三.方法级缓存 四.连接池 小结 一.简介 在 补习系列(A3 ...
- 补习系列(15)-springboot 分布式会话原理
目录 一.背景 二.SpringBoot 分布式会话 三.样例程序 四.原理进阶 A. 序列化 B. 会话代理 C. 数据老化 小结 一.背景 在 补习系列(3)-springboot 几种scope ...
- 补习系列(17)-springboot mongodb 内嵌数据库
目录 简介 一.使用 flapdoodle.embed.mongo A. 引入依赖 B. 准备测试类 C. 完善配置 D. 启动测试 细节 二.使用Fongo A. 引入框架 B. 准备测试类 C.业 ...
- 补习系列(17)-springboot mongodb 内嵌数据库【华为云技术分享】
目录 简介 一.使用 flapdoodle.embed.mongo A. 引入依赖 B. 准备测试类 C. 完善配置 D. 启动测试 细节 二.使用Fongo A. 引入框架 B. 准备测试类 C.业 ...
- 补习系列(16)-springboot mongodb 数据库应用技巧
目录 一.关于 MongoDB 二.Spring-Data-Mongo 三.整合 MongoDB CRUD A. 引入框架 B. 数据库配置 C. 数据模型 D. 数据操作 E. 自定义操作 四.高级 ...
- 补习系列(19)-springboot JPA + PostGreSQL
目录 SpringBoot 整合 PostGreSQL 一.PostGreSQL简介 二.关于 SpringDataJPA 三.整合 PostGreSQL A. 依赖包 B. 配置文件 C. 模型定义 ...
- 补习系列(8)-springboot 单元测试之道
目录 目标 一.About 单元测试 二.About Junit 三.SpringBoot-单元测试 项目依赖 测试样例 四.Mock测试 五.最后 目标 了解 单元测试的背景 了解如何 利用 spr ...
- 补习系列(6)- springboot 整合 shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- 补习系列(3)-springboot中的几种scope
目标 了解HTTP 请求/响应头及常见的属性: 了解如何使用SpringBoot处理头信息 : 了解如何使用SpringBoot处理Cookie : 学会如何对 Session 进行读写: 了解如何在 ...
随机推荐
- Elasticsearch JavaApi
官网JavaApi地址:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-search.html 博 ...
- jieba库分词
(1)团队简介的词频统计 import jieba import collections s="制作一个购票小程序,这个购票小程序可以根据客户曾经的购票历史" s+="和 ...
- LVM基本应用,扩展及缩减实现!
LVM概述 [百度百科] LVM是逻辑盘卷管理(LogicalVolumeManager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和 分区之上的一个逻辑层,来提高磁 ...
- Xamarin.Android 使用AsyncTask提示上传动态
我们有时候会通过WebServices上传数据,如果信息量过大并没有提示,用户会觉得是死机,或是系统崩溃,这时候我们可以用到AsyncTask(异步任务)来提示上传信息,例如:正在上传数据... 这里 ...
- Tornado day1
Tornado 之路由配置 首先导入模块,使用Application方法中可配置多个路由,格式必须为列表中是元组 元组的第一个是配置的url,第二个参数时自定义的类(继承自RequestHandler ...
- synchronized修饰方法和代码块的区别
先看一段代码 Class A { public synchronized methodA() {//对当前对象加锁 } public methodB() { synchronized(this){}/ ...
- MYSQL复制原理及其流程
Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其他主机(slave)上,并重新执行一遍来实现 ...
- sql中having、group by用法及常用聚合函数
having是用在聚合函数的用法.当我们在用聚合函数的时候,一般都要用到GROUP BY 先进行分组,然后再进行聚合函数的运算.运算完后就要用到HAVING 的用法了,就是进行判断了. 注意:sele ...
- SSM-SpringMVC-26:SpringMVC异常骇级之自定义异常注解版
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 注解的方法实现异常解析,话不多说,直接搞起,和以前一样的习惯,和上篇博客一样的代码放后面,不一样的在前面 案 ...
- PHP 的 uniqid 函数产生的 id 真的是唯一的么?
PHP 的 uniqid 函数产生的 id 真的是唯一的么? 最近使用到了 uniqid,就产生了疑问?uniqid 生成的 id 由什么组成?真的是唯一的么?什么情况下会产生冲突? 从文档中看到 u ...