H2 内存模式是 H2 数据库提供的一种特殊运行模式。
在 H2 内存模式下,数据库将所有的数据存储在内存(RAM)中,而不是像传统数据库那样存储在磁盘上。这意味着数据的读写操作直接在内存中进行,无需进行磁盘 I/O 操作。例如,当执行一条 SQL 查询语句来检索数据时,数据直接从内存中的数据结构中获取,而不是从磁盘文件中读取。
由于数据存储在内存中,这种模式下的数据库具有临时性。一旦数据库连接关闭或者应用程序终止,内存中的数据将会丢失。这是因为内存是易失性存储介质,当与之相关的进程结束时,其所占用的内存空间会被释放。
典型的用于连接 H2 内存模式数据库的连接字符串格式为:
jdbc:h2:mem: [databaseName]
其中:
jdbc 表示这是一个 Java 数据库连接(JDBC)的连接字符串;
h2 指定了要连接的数据库为 H2 数据库;
mem 表明是内存模式;
[databaseName] 是数据库的名称,可以自行指定,例如 jdbc:h2:mem:test 中的 test 就是数据库名称。
除了上述标准字段外,还可以在连接字符串中添加一些参数来调整数据库的行为。例如,DB_CLOSE_DELAY=-1 可以添加到连接字符串中,如 jdbc:h2:mem:test;DB_CLOSE_DELAY=-1。这个参数的作用是在最后一个连接关闭后,不立即关闭数据库。在默认情况下(没有这个参数或者参数值为 0 时),当最后一个连接关闭时,内存数据库会立即关闭,导致数据丢失。但设置 DB_CLOSE_DELAY=-1后,数据库在连接关闭后仍会保留一段时间,这在某些测试场景下非常有用,例如在测试用例之间需要共享数据库状态时。
在进行 Java 单元测试时,经常需要创建一个临时的数据库环境来测试数据库相关的代码逻辑。H2 内存模式非常适合这种场景,因为它可以快速创建和销毁数据库实例,而且不会对磁盘上的文件系统造成任何持久化的影响。例如,在测试一个数据访问层(DAO)类时,可以使用 H2 内存模式数据库来模拟真实的数据库操作,如插入、查询、更新和删除数据等操作,确保 DAO 类的方法在各种情况下都能正确工作。
当开发人员在项目的早期阶段进行快速原型开发时,可能需要一个简单、快速的数据库解决方案来验证业务逻辑和数据处理流程。H2 内存模式的快速读写特性使得它成为一个理想的选择。开发人员可以快速地在内存中创建数据库结构,插入一些测试数据,然后进行业务逻辑的开发和验证,而不必担心数据库的复杂配置和持久化存储问题。
对于一些只在程序运行期间需要临时存储的数据,H2 内存模式也可以作为一种有效的数据缓存解决方案。例如,在一个复杂的计算任务中,某些中间结果只需要在当前计算过程中使用,不需要持久化到磁盘上。可以将这些中间结果存储在 H2 内存模式数据库中,以便在后续的计算步骤中快速访问,提高计算效率。
使用 JDBC 连接到 H2 内存数据库,然后创建 person 数据表,以及插入数据、查询数据操作,如下:
package com.hxstrive.h2.memory_database; import java.sql.*; /** * H2内存数据库示例 * @author hxstrive.com * @since 1.0.0 2024/2/18 15:18 **/ public class H2MemoryDatabaseExample { private static final String DB_DRIVER = "org.h2.Driver"; private static final String DB_CONNECTION = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"; private static final String DB_USER = "sa"; private static final String DB_PASSWORD = ""; public static void main(String[] args) throws Exception { Connection connection = null; PreparedStatement createPs = null; PreparedStatement insertPs = null; PreparedStatement selectPs = null; try { // 获取连接 Class.forName(DB_DRIVER); connection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD); // 设置不自动提交 connection.setAutoCommit(false); // 创建数据表 createPs = connection.prepareStatement("CREATE TABLE PERSON(id int primary key, name varchar(255))"); createPs.executeUpdate(); // 插入数据 insertPs = connection.prepareStatement("INSERT INTO PERSON(`id`, `name`) values (?,?)"); insertPs.setInt(1, 1); insertPs.setString(2, "Jose"); insertPs.executeUpdate(); // 查询数据 selectPs = connection.prepareStatement("select * from PERSON"); ResultSet rs = selectPs.executeQuery(); while (rs.next()) { System.out.println("Id=" + rs.getInt("id") + " Name=" + rs.getString("name")); } // 提交事务 connection.commit(); } catch (Exception e) { e.printStackTrace(); // 回滚事务 if(null != connection) { connection.rollback(); } } finally { // 释放资源 if(null != selectPs) { selectPs.close(); } if(null != insertPs) { insertPs.close(); } if(null != createPs) { createPs.close(); } if(null != connection) { connection.close(); } } } }
运行示例,输出如下:
Id=1 Name=Hello World
连接地址“jdbc:h2:mem:test;DB_CLOSE_DELAY=-1”说明:
jdbc - 这是 Java Database Connectivity(Java 数据库连接)的缩写,它是 Java 语言中用于执行 SQL 语句与数据库进行交互的 API 规范。Java 程序通过 JDBC 来连接各种不同的数据库,如 MySQL、Oracle、H2 等。
h2 - 表示要连接的数据库是 H2 数据库。
mem:test -“mem” 表示内存模式。在这种模式下,H2 数据库将数据存储在内存中,而不是磁盘上。这使得数据库的操作速度非常快,适合用于单元测试等场景。当数据库运行在内存模式时,一旦应用程序关闭或者数据库连接关闭,数据库中的数据将会丢失。“test”是数据库的名称,你可以根据需要将其替换为其他名称,用于标识这个特定的内存数据库实例。
DB_CLOSE_DELAY=-1 - 在 H2 数据库中,这个参数用于控制数据库关闭的延迟时间。当设置为 - 1 时,表示在最后一个连接关闭后,不立即关闭数据库。在内存模式下,如果没有这个参数或者设置为其他值(例如默认值为 0,表示在最后一个连接关闭时立即关闭数据库),一旦连接关闭,数据库中的所有数据都会丢失。通过设置 DB_CLOSE_DELAY = - 1,可以在连接关闭后仍然保留数据库中的数据,这对于一些测试场景非常有用,例如在测试用例之间需要共享数据库状态时,可以确保数据不会因为连接的关闭而丢失。