内存数据库:H2

2021-02-06  本文已影响0人  hemiao3000

测试持久层(Dao 层)的难点在于:

  • 单元测试必须执行隔离的代码;而持久层的代码需要和数据库进行交互。
  • 单元测试必须快速运行;而访问数据库却相对较慢。

以上两个难点决定了嵌入式数据库(H2、HSQLDB、Derby 和 Java DB)的使用价值。嵌入式数据库使用场景较少,但是是配合 JUnit 测试持久层的最佳选择。

1. 基本使用

pom.xml 中添加 h2 数据库的依赖。如果是在非 Maven 项目中使用,则下载该 h2 的 .jar 包并加入项目的 classpath 中。

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
    <scope>test</scope>
</dependency>

嵌入式数据库 H2 有多种使用模式,也可以将数据写入到磁盘上的文件中,但是大家更关注它的『内存模式』。即,将 database 和 table 建立在内存中。

private static final String DRIVER = "org.h2.Driver";
private static final String URL = "jdbc:h2:mem:scott;MODE=MYSQL;DB_CLOSE_DELAY=-1";
private static final String USERNAME = "sa";
private static final String PASSWORD = "";
Class.forName(DRIVER);

Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

Statement stmt = conn.createStatement();
stmt.execute( "...");

除了正常的使用获得数据库 Connection 对象之外,H2 自带了连接池功能。

JdbcConnectionPool cp = JdbcConnectionPool.create(URL, USERNAME, PASSWORD);
Connection conn = cp.getConnection();

2. 初始化数据库

虽然可以在 JUnit 的 Before 方法中通过执行 SQL 语句的方式在 @Test 之前去初始化数据库环境,但是 H2 有一个更好的特性能实现数据库的初始化操作:Execute SQL on connection

H2 支持在连接上数据库的时候就执行 SQL 语句,相当于就初始化了数据库环境:

jdbc:h2:mem:<database>;...;INIT=RUNSCRIPT FROM '~/create.sql'

spring.datasource.url=jdbc:h2:mem:scott;MODE=MYSQL;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM './src/test/resources/create.sql'

H2 internally uses Unicode, and supports all character encoding systems and character sets supported by the virtual machine you use.

可以为测试类编写父类,并实现 @Before 方法,以方便/确保于在每个 @Test 方法前执行统一的初始化数据库(初始化测试环境)的代码。

public class DaoTestBase {

    private static final String DRIVER = "org.h2.Driver";
    private static final String URL = "jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1";
    private static final String USERNAME = "sa";
    private static final String PASSWORD = "";

    @Before
    public void setUp() throws URISyntaxException, ClassNotFoundException, SQLException {
        String sqlPathName = getClass().getResource("/conf/sql/xxx.sql" ).toURI().toString().substring(6);

        Class.forName(DRIVER);
        Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

        Statement stmt = conn.createStatement();
        stmt.execute( "runscript from '" + sqlPathName + "'");

        stmt.close();
        conn.close();
    }


}

三、H2 和 MySQL 的语法兼容性

所有的数据库都会有些小区别,即便是与 MySQL『最像』的数据库,H2 与 MySQL 仍有一些小区别:

上一篇 下一篇

猜你喜欢

热点阅读