補習系列(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篇" ,期待更多精彩內容^-^