You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用嵌入式H2文件数据库时,Jooq插入数据重启后丢失

解决Jooq操作H2嵌入式数据库数据重启丢失问题

问题原因

你的代码中使用classpath资源路径作为H2数据库文件的存储位置,这会触发两个核心问题:

  1. Classpath中的资源文件通常是只读的,尤其是应用打包成JAR包时,无法直接写入JAR内部的文件;
  2. 即使临时能写入,JVM可能会将classpath资源解压到临时目录,重启应用后临时目录被清理,数据自然丢失。

插入后能查询到数据是因为数据还在当前连接的内存缓存中,并未真正持久化到正确的文件位置。

解决方案

1. 修改数据库文件存储路径

放弃使用classpath资源,改用应用拥有写入权限的本地文件路径(比如用户目录、应用专属数据目录):

// 示例:将数据库文件存储到用户主目录下的app-data文件夹
private val dbDir = System.getProperty("user.home") + "/app-data"
private val dbPath = "$dbDir/mock-data.db"
// 提前创建目录,避免H2因路径不存在创建失败
File(dbDir).mkdirs()

private val conn = DriverManager.getConnection("jdbc:h2:file:$dbPath;AUTO_SERVER=TRUE")
val appDslContext get(): DSLContext = DSL.using(conn, SQLDialect.H2)

2. 确认事务提交机制

虽然H2默认开启自动提交,但如果代码中手动关闭了自动提交,需要显式提交事务:

// 显式开启自动提交(可选,默认已开启)
conn.autoCommit = true

// 或者用Jooq的事务API包裹写入操作,确保数据持久化
appDslContext.transaction { txConfig ->
    val txDsl = DSL.using(txConfig)
    txDsl.newRecord(MonitorAlarmEvent.MONITOR_ALARM_EVENT).apply {
        from(alarmEvent)
    }.insert()
}

3. 检查连接参数与权限

  • 确保H2连接URL包含file:前缀,明确指定文件存储模式(而非内存模式);
  • 验证目标路径的写入权限,若权限不足,H2会自动切换为内存数据库,导致数据无法持久化。

验证方法

重启应用后,检查指定路径下是否生成了mock-data.db.mv.db(H2的实际数据文件),如果文件存在且大小不为0,说明数据已正确持久化。

内容的提问来源于stack exchange,提问作者kio v

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:17:44