1. 程式人生 > >記憶體資料庫-H2簡介與實踐

記憶體資料庫-H2簡介與實踐

一、H2資料庫介紹
  H2資料庫地址:http://www.h2database.com/html/main.html

  H2是一個開源的嵌入式(非嵌入式裝置)資料庫引擎,它是一個用Java開發的類庫,可直接嵌入到應用程式中,與應用程式一起打包釋出,不受平臺限制。
  

1.1 與其他開源資料庫比較

  H2與Derby、HSQLDB、MySQL、PostgreSQL等開源資料庫相比,H2的優勢為:a.存Java開發,不受平臺限制;b.H2只有一個jar包,佔用空間小,適合嵌入式資料庫;c.有web控制檯,用於管管理資料庫。具體特徵如下:

特徵 H2 Derby HSQLDB MySQL PostgreSQL
純Java yes yes yes no no
支援記憶體模式 yes yes yes no no
支援資料庫加密 yes yes yes no no
支援ODBC驅動 yes no no yes yes
支援全文檢索 yes no no yes yes
支援多版本併發控制 yes no yes yes yes
佔用空間(jar/dll) ~1M ~2M ~1M ~4M ~6M
* 1.2 H2資料庫連線方式

  H2資料庫支援如下三種連線方式:

連線方式 描述
嵌入式模式 本地JDBC連線
伺服器模式 JDBC或基於tcp/ip的ODBC遠端連線
混合模式 本地或遠端同時連線
注:三種模式都支援記憶體、持久化到檔案兩種資料儲存方式。三種模式對同時開啟的資料庫數量和資料庫連線數量沒有限制。

嵌入式模式

  嵌入式模式是最簡單最快捷的一種連線方式,嵌入式模式下,應用在JVM中啟動H2資料庫並通過JDBC連線。該模式同時支援資料持久化和內容兩種方式,對同時開啟的資料庫數量和資料庫連線數量沒有限制。示意圖如下:

 

伺服器模式

  伺服器模式下,應用通過JDBC或ODBC API遠端開啟資料庫。該模式下,H2資料庫可以部署在不同的JVM或不同的物理機中,多個應用可以通過連線H2伺服器同時連線到H2資料庫。因為資料需要通過TCP/IP協議遠端傳輸,因此伺服器模式獲取資料比嵌入式模式慢。伺服器模式示意圖如下:

 

混合模式

  混合模式結合了嵌入式模式和伺服器模式的特點,第一個應用通過嵌入式模式開啟H2資料庫,同時將資料庫開啟伺服器模式,其他應用可以遠端連線到資料庫。資料庫伺服器的開啟和關閉都在第一個應用中完成。混合模式示意圖如下:

 

1.3 H2資料庫JDBC URL格式

  H2資料庫支援多種連線方式和連線設定,連線URL格式如下,URL中的設定大小寫不敏感。

主題 URL格式 範例
本地嵌入式連線 jdbc:h2:[file:][]< databaseName> jdbc:h2:~/test
jdbc:h2:file:/data/sample
jdbc:h2:file:C:/data/sample (Windows only)
記憶體模式(private) jdbc:h2:mem:
記憶體模式(named) jdbc:h2:mem:< databaseName> jdbc:h2:mem:test_mem
伺服器模式(TCP/IP) jdbc:h2:tcp://[:]/[]< databaseName> jdbc:h2:tcp://localhost/~/test
jdbc:h2:tcp://dbserv:8084/~/sample
jdbc:h2:tcp://localhost/mem:test
伺服器模式(TLS) jdbc:h2:ssl://[:]/< databaseName> jdbc:h2:ssl://localhost:8085/~/sample;
加密方式 jdbc:h2:< url>;CIPHER=AES jdbc:h2:ssl://localhost/~/test;CIPHER=AES
jdbc:h2:file:~/secure;CIPHER=AES
文件鎖定 jdbc:h2:< url>;FILE_LOCK={FILE|SOCKET|NO} jdbc:h2:file:~/private;CIPHER=AES;FILE_LOCK=SOCKET
僅存在時開啟 jdbc:h2:< url>;IFEXISTS=TRUE jdbc:h2:file:~/sample;IFEXISTS=TRUE
VM存在時不關閉資料庫 jdbc:h2:< url>;DB_CLOSE_ON_EXIT=FALSE
使用者名稱、密碼 jdbc:h2:< url>[;USER=< username>][;PASSWORD=< value>] jdbc:h2:file:~/sample;USER=sa;PASSWORD=123
除錯日誌設定 jdbc:h2:< url>;TRACE_LEVEL_FILE=< level 0..3> jdbc:h2:file:~/sample;TRACE_LEVEL_FILE=3
忽略不明設定 jdbc:h2:;IGNORE_UNKNOWN_SETTINGS=TRUE
使用者檔案訪問 jdbc:h2:;ACCESS_MODE_DATA=rws
zip格式資料庫檔案 jdbc:h2:zip:< zipFileName>!/< databaseName> jdbc:h2:zip:~/db.zip!/test
相容模式 jdbc:h2:< url>;MODE=< databaseType> jdbc:h2:~/test;MODE=MYSQL
自動重新連線 jdbc:h2:< url>;AUTO_RECONNECT=TRUE jdbc:h2:tcp://localhost/~/test;AUTO_RECONNECT=TRUE
自動混合模式 jdbc:h2:< url>;AUTO_SERVER=TRUE jdbc:h2:~/test;AUTO_SERVER=TRUE
頁面大小 jdbc:h2:< url>;PAGE_SIZE=512
修改其他設定 jdbc:h2:< url>;< setting>=< value>[;< setting>=< value>…] jdbc:h2:file:~/sample;TRACE_LEVEL_SYSTEM_OUT=3
二、H2資料庫控制檯
  H2控制檯應用允許通過瀏覽器的方式連線到H2資料庫,示意圖如下。這是典型Client/Server模式,因此同時需要伺服器和客戶端。

 

  H2控制檯在不同的作業系統下有不同的啟動方式,筆者系統是Mac os,下文通過命令列啟動,如下:

java -jar h2*.jar
1
  H2資料庫伺服器啟動後會自動開啟web控制檯,也可以通過:http://localhost:8082 訪問。控制檯介面如下:

 

可以在H2控制檯設定資料庫連線模式,本文設定為伺服器模式,首次進入可以設定使用者名稱和密碼,第一次測試連線後生效,連線進入到資料庫控制介面,如下。在該介面下可執行資料庫相關的DDL、DML語句。

 

注:如果資料庫開啟方式為嵌入式模式,則不允許其他應用在啟動控制檯時同時連線到資料庫;如果開啟模式為伺服器模式或混合模式,則允許其他應用同時連線到資料庫

三、H2資料庫實踐
  Spring+Mybatis+Mysql資料庫的相關配置參考:Spring事務管理-程式設計式事務、宣告式事務,本文介紹Spring+Mybatis+H2的資料庫訪問實踐。Spring+Mybatis配置參考上一篇文章,本次事件新新增H2資料庫依賴:

...
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.190</version>
</dependency>
...
1
2
3
4
5
6
7
  H2資料庫屬性檔案配置如下,本文采用記憶體模式訪問H2資料庫:

driver=org.h2.Driver
# 記憶體模式
url=jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1
# 持久化模式
#url= jdbc:h2:tcp://localhost/~/test1;MODE=MYSQL;DB_CLOSE_DELAY=-1
1
2
3
4
5
  H2資料庫訪問的Spring配置檔案為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">

<!-- 引入屬性檔案 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>

<!-- 自動掃描DAO -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xiaofan.test" />
</bean>

<!-- 配置Mybatis sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis_config.xml"/>
<property name="mapperLocations" value="classpath:user_mapper.xml"/>
</bean>

<!-- 配置資料來源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<!--<property name="username" value="sa" />-->
<!--<property name="password" value="123" />-->
</bean>

<!-- 初始化資料庫 -->
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:sql/ddl.sql" />
<jdbc:script location="classpath:sql/dml.sql" />
</jdbc:initialize-database>

<!-- 配置事務管理 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  其中初始化資料庫的DDL語句檔案為:

CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
1
2
3
4
5
6
  初始化資料庫的DML語句檔案為:

insert into `user` (`id`,`name`,`age`) values (1, 'Jerry', 27);
insert into `user` (`id`,`name`,`age`) values (2, 'Angel', 25);
1
2
  編寫測試檔案,如下:

/**
* Created by Jerry on 17/7/30.
*/
@ContextConfiguration(locations = {"classpath:config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class Test extends AbstractJUnit4SpringContextTests{

@Resource
UserDAO userDAO;

@org.junit.Test
public void testInsert() {

int result = userDAO.insert(new User(null, "LiLei", 27));

Assert.assertTrue(result > 0);
}

@org.junit.Test
public void testUpdate() {
int result = userDAO.update(new User(2L, "Jerry update", 28));

Assert.assertTrue(result > 0);
}

@org.junit.Test
public void testSelect() {
User result = userDAO.findByName(new User(null, "Jerry", null));

Assert.assertTrue(result.getAge() != null);
}

@org.junit.Test
public void testDelete() {
int result = userDAO.delete("Jerry");

Assert.assertTrue(result > 0);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  測試結果通過!
---------------------
作者:Jerry的技術部落格
來源:CSDN
原文:https://blog.csdn.net/xktxoo/article/details/78014739
版權宣告:本文為博主原創文章,轉載請附上博文連結!