内存数据库-H2简介与实践

7,015 阅读6分钟
原文链接: blog.csdn.net

一、H2数据库介绍

  H2数据库地址:www.h2database.com/html/main.h…

  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

  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>
...

  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

  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>

  其中初始化数据库的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`)
);

  初始化数据库的DML语句文件为:

insert into `user` (`id`,`name`,`age`) values (1, 'Jerry', 27);
insert into `user` (`id`,`name`,`age`) values (2, 'Angel', 25);

  编写测试文件,如下:

/**
 * 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);
    }

}

  测试结果通过!