【问题标题】:Can I persist some data into H2 database using in-memory mode?我可以使用内存模式将一些数据保存到 H2 数据库中吗?
【发布时间】: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

如提到的herehere

然后,是的,我在刷新后看到数据库中的数据,数据将以如下格式保存:

但是我可以对in-memory 做同样的事情吗?

我将不胜感激。

UPD #1:

例如表示here

“大多数内存数据库系统都提供持久性,至少作为 选项。”

UPD #2:

来自H2-console 我使用in-memory 模式查看数据,但来自Intellij Idea - 不是:

UPD #3:@Turing85 所述,我已经测试了url:jdbc:h2:tcp://localhost/mem:db1 以通过TCP/IPTLS 访问数据库,但此链接在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 等工具,我们可以在几分钟内建立并运行数据库。
  • 内存数据库仅在内存中时才处于活动状态。默认情况下,数据库与您的应用程序在同一进程中运行。所以应用程序将数据添加到数据库并且数据就在那里。但应用程序结束,数据库被破坏。那可能不是你想要的。此外,在内存中通常不被认为是持久的。正是因为这个原因。
  • 恭喜!您在一台机器上启动了两个完全独立的内存数据库实例。

标签: java h2


【解决方案1】:

正如提到的Turing85Elliott FrischM. Deinumin-memory数据库与正在运行的Spring Boot应用程序是隔离的,这就是为什么我需要使用其他模式,例如:

spring.datasource.url=jdbc:h2:file:./data/testdb;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE

spring.datasource.url=jdbc:h2:./data/testdb;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=10990

【讨论】:

    猜你喜欢
    • 2017-06-16
    • 2011-07-10
    • 2012-10-06
    • 1970-01-01
    • 2012-03-24
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多