如何跨多个 Spring Boot 应用程序共享 H2 内存数据库?

Posted

技术标签:

【中文标题】如何跨多个 Spring Boot 应用程序共享 H2 内存数据库?【英文标题】:How do I share H2 in-memory database across multiple Spring boot applications? 【发布时间】:2019-03-21 03:23:50 【问题描述】:

这是与其他已回答问题不同的情况。我有一个使用嵌入式 H2 内存数据库并将其公开为服务器的 Spring Boot 应用程序(应用程序 #1)。我的第二个 Spring 引导应用程序(应用程序 #2)从应用程序 #1 连接到 H2 服务器,并且工作正常。我可以从 H2 存储和检索数据。现在问题来了。我有第三个 Spring Boot(应用程序 #3),它从应用程序 #1 连接到 H2 服务器。连接有效,但它(问题 #1)清除了之前由应用 #2 存储的所有数据。在此之后,现在应用程序#2 和#3 都可以存储和检索其数据以及彼此的数据。现在我终止了应用程序 #2 或应用程序 #3,并且(问题 #2)剩余的应用程序无法继续使用 H2 内存数据库。问题 #1 和 #2 是正常行为吗?如果没有,我该如何解决它们?我希望我的 H2 数据在应用 #1(H2 服务器)运行期间一直保留,即使其他应用已断开连接,并且我不希望在新应用连接到 H2 服务器时清除我的数据。

【问题讨论】:

H2 服务器和其他两个应用程序之间的“连接”是什么?它们是否涉及某种将数据库清理行为附加到它关闭时发生的上下文? - 例如,如果您正在进行 Spring MVC REST 调用以访问 H2 数据库,那么这些来来往往的连接(它们无论如何都是无状态的)完全没有理由影响数据库上下文。重要的是您为响应每个 REST 调用而运行的代码。 @Steve 对于应用程序 #1,这里是“application.properties”行 spring.datasource.url=jdbc:h2:mem:mydb 对于应用程序 #2 和应用程序 3,这里是行:spring .datasource.url=jdbc:h2:tcp://localhost:9090/mem:mydb 这是我遵循的示例:baeldung.com/spring-boot-access-h2-database-multiple-apps @Steve 这是应用程序 #1 的服务器代码:@Bean(initMethod = "start", destroyMethod = "stop") public Server inMemoryH2DatabaseaServer() throws SQLException return Server.createTcpServer("-tcp ", "-tcpAllowOthers", "-tcpPort", "9090"); 哇!你每天都会学到一些东西。我从来没有想过要做那样的事情,甚至不知道这是可能的。我原以为内存数据库对于托管它的进程来说是私有的。根据您的要求,我怀疑是这样的。由于我还没有这样做,所以我不知道这样做应该会产生什么行为。也许真正做到这一点的人会出现。否则,我会说看看可用的文档,也许谷歌在其他地方寻找答案。 我假设你已经明白你可以实现一个耦合度较低的 REST API 并避免你的问题。我了解您是否想尝试使用此方法。 - 我一直在谷歌搜索。我没有看到任何暗示你不会得到你期望的行为的东西......只是共享数据库。奇怪。 【参考方案1】:

在此处的文档中找到此内容:https://h2database.com/html/features.html

默认情况下,关闭与数据库的最后一个连接会关闭 数据库。对于内存数据库,这意味着内容丢失。 要保持数据库打开,请将 ;DB_CLOSE_DELAY=-1 添加到数据库 URL。 将内存数据库的内容与虚拟数据库一样长 机器还活着,使用 jdbc:h2:mem:test;DB_CLOSE_DELAY=-1。

所以我认为如果您将应用程序#1 的 application.properties 文件中的 db 行设置为:

spring.datasource.url=jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1

如果这能解决您的问题,请告诉我,因为我很好奇。您的描述似乎表明它比这更复杂...涉及的两个应用程序的重叠访问...但这听起来确实像您缺少的那种参数。

【讨论】:

【参考方案2】:

我是这样做的,在你的spring配置中注册多个H2服务器

@Bean(initMethod = "start", destroyMethod = "stop")
public Server h2Server1() throws SQLException 
    return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "9080");


// Second App
@Bean(initMethod = "start", destroyMethod = "stop")
public Server h2Server2() throws SQLException 
    return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "9081");

然后在连接到配置下使用的 H2 时

对于基于文件的 H2

url=jdbc:h2:tcp://localhost:9081/<path to H2>
username=sa
password=sa

用于内存 H2 数据库

url=jdbc:h2:tcp://localhost:9081/<H2 database name>
username=sa
password=sa

【讨论】:

以上是关于如何跨多个 Spring Boot 应用程序共享 H2 内存数据库?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 最简单的解决跨域问题

Spring Boot 最简单的解决跨域问题

在 Grails 中跨多个插件共享身份验证

Spring Boot如何让某个Controller支持跨源请求,以及如何让Controller类某个成员方法支持跨源请求

在 Spring Boot 中的多个连接器之间共享嵌入式 Tomcat 执行器

spring boot + redis 实现session共享分析