關於 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篇" ,期待更多精彩內容-