【发布时间】:2021-10-06 16:31:32
【问题描述】:
我想使用h2 作为数据库将数据完全保存在in-memory mode 中。
所以我有 application.properties 文件,其配置如下:
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=...
spring.datasource.password=...
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.session.jdbc.initialize-schema=always
使用特定参数:
DB_CLOSE_DELAY=-1 - 保持数据库打开/只要虚拟机处于活动状态就保持内存数据库的内容DB_CLOSE_ON_EXIT=FALSE - 禁用退出时关闭数据库
如H2 database 的文档中所述。
同时,我使用Entity 保存到数据库中:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity(name = "address_entity")
@Table(name = "addresses")
public class GeolocationAddress {
public GeolocationAddress(GeolocationAddressDTO geolocationAddressDTO) {
this.displayName = geolocationAddressDTO.getDisplayName();
this.lat = geolocationAddressDTO.getLat();
this.lon = geolocationAddressDTO.getLon();
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "address_id")
private Integer id;
private String displayName;
private String lat;
private String lon;
}
发送请求后,我从Hibernate获取控制台信息:
Hibernate: insert into addresses (address_id, display_name, lat, lon) values (null, ?, ?, ?)
Hibernate: insert into addresses (address_id, display_name, lat, lon) values (null, ?, ?, ?)
但在使用 Ctrl+F5 组合或通过以下方式刷新Data Source 中的H2 数据库后:
关键,我没有看到任何数据。
为了研究这种行为,我检查了documentation 中的公式:
"对于某些用例(例如:快速原型、测试、高 性能操作,只读数据库),可能不需要 持久化数据,或持久化对数据的更改。这个数据库 支持内存模式,数据不持久化。”
来自一些articles,例如:
“根据设计,内存数据库是易失性的,数据会丢失 当我们重新启动应用程序时。”
或this一:
"H2 是内存数据库。它不是持久化数据库。 H2 是一个很好的学习工具,因为您需要零设置。”
但我还是不完全明白,我可以在应用程序运行时以这种模式保存数据吗?
如果我换成另一种模式,例如:
spring.datasource.url=jdbc:h2:file:./data/demo;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE
然后,是的,我在刷新后看到数据库中的数据,数据将以如下格式保存:
但是我可以对in-memory 做同样的事情吗?
我将不胜感激。
UPD #1:
例如表示here:
“大多数内存数据库系统都提供持久性,至少作为 选项。”
UPD #2:
来自H2-console 我使用in-memory 模式查看数据,但来自Intellij Idea - 不是:
UPD #3:
如@Turing85 所述,我已经测试了url:jdbc:h2:tcp://localhost/mem:db1 以通过TCP/IP 或TLS 访问数据库,但此链接在Data Source 中无效。
经过一番调查,我找到了useful information:
":mem 不适用于 TCP 连接。因此请删除 :mem 连接地址”
另一种方式,例如:jdbc:h2:./data/testdb;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=10990
也可以。
UPD #4: 大概,这个answer也和我的问题有关。
【问题讨论】:
-
“以这种模式保存数据”是什么意思?您可以保存数据并随后获取该数据,是的。但是,如文档中所述,数据是不稳定的,即当您停止/重新启动应用程序时会消失。
-
您不能简单地从另一个进程“连接”到内存数据库。 documentation you linked 中也提到了这一点:“要从另一个进程或从另一台计算机访问内存数据库,您需要在创建内存数据库的同一进程中启动 TCP 服务器。然后其他进程需要通过 TCP/IP 或 TLS 访问数据库,使用数据库 URL,例如:
jdbc:h2:tcp://localhost/mem:db1。" 如果写入文件的过程有效,请改用它。 -
旁注:如果可能,我建议使用您想在生产中使用的数据库实例,例如mysql 或 postgres 来改进 dev-prod-parity。使用 docker 或 podman 等工具,我们可以在几分钟内建立并运行数据库。
-
内存数据库仅在内存中时才处于活动状态。默认情况下,数据库与您的应用程序在同一进程中运行。所以应用程序将数据添加到数据库并且数据就在那里。但应用程序结束,数据库被破坏。那可能不是你想要的。此外,在内存中通常不被认为是持久的。正是因为这个原因。
-
恭喜!您在一台机器上启动了两个完全独立的内存数据库实例。