使用嵌入式H2文件数据库时,Jooq插入数据重启后丢失
解决Jooq操作H2嵌入式数据库数据重启丢失问题
问题原因
你的代码中使用classpath资源路径作为H2数据库文件的存储位置,这会触发两个核心问题:
- Classpath中的资源文件通常是只读的,尤其是应用打包成JAR包时,无法直接写入JAR内部的文件;
- 即使临时能写入,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
相关产品推荐
相关产品推荐

