1. Overview
1.概述
In this quick tutorial, we’ll demonstrate how to access the same in-memory H2 database from multiple Spring Boot applications.
在这个快速教程中,我们将演示如何从多个Spring Boot应用程序访问同一个内存H2数据库。
To do this, we’ll create two distinct Spring Boot applications. The first Spring Boot application will start an in-memory H2 instance, whereas the second one will access an embedded H2 instance of the first application over TCP.
要做到这一点,我们将创建两个不同的Spring Boot应用程序。第一个Spring Boot应用程序将启动一个内存H2实例,而第二个将通过TCP访问第一个应用程序的嵌入式H2实例。
2. Background
2. 背景
As we know, an in-memory database is faster and often used in an embedded mode within an application. However, the in-memory database doesn’t persist data across server restarts.
正如我们所知,内存数据库的速度更快,而且经常在应用程序中以嵌入式模式使用。然而,内存数据库并不能在服务器重启时持久保存数据。
For additional background, please check our articles on the most commonly used in-memory databases and the usage of an in-memory database in automated testing.
有关其他背景,请查看我们关于最常用的内存数据库和自动测试中内存数据库的使用的文章。
3. The Maven Dependencies
3.Maven的依赖性
The two Spring Boot applications in this article require the same dependencies:
本文中的两个Spring Boot应用程序需要相同的依赖性:。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
4. Setting Up the H2 Datasource
4.设置H2数据源
Firstly, let’s define the most important component — a Spring bean for an in-memory H2 database — and expose it via a TCP port:
首先,让我们定义最重要的组件–内存H2数据库的Spring Bean–并通过TCP端口将其公开。
@Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseaServer() throws SQLException {
return Server.createTcpServer(
"-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}
The methods defined by the initMethod and destroyMethod parameters are called by Spring to start and stop H2 database.
由initMethod和destroyMethod参数定义的方法被Spring调用以启动和停止H2数据库。
The -tcp parameter instructs H2 to use a TCP server to launch H2. We specify the TCP port to be used in the third and fourth parameters of the createTcpServer method.
-tcp参数指示H2使用一个TCP服务器来启动H2。我们在createTcpServer方法的第三和第四个参数中指定要使用的TCP端口。
The parameter tcpAllowOthers opens up H2 for access from external applications running on the same host or remote hosts.
参数tcpAllowOthers打开了H2,以便从运行在同一主机或远程主机上的外部应用程序访问。
Next, let’s override the default data source created by Spring Boot’s auto-configuration feature by adding a few properties to the application.properties file:
接下来,让我们通过在application.properties文件中添加一些属性来覆盖Spring Boot的自动配置功能所创建的默认数据源。
spring.datasource.url=jdbc:h2:mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create
It’s important to override these properties because we’ll need to use the same properties and values in the other applications that want to share the same H2 database.
覆盖这些属性很重要,因为我们需要在其他想要共享同一个H2数据库的应用程序中使用相同的属性和值。
5. Bootstrapping the First Spring Boot Application
5.引导第一个Spring Boot应用程序
Next, to bootstrap our Spring Boot application, we’ll create a class with the @SpringBootApplication annotation:
接下来,为了引导我们的Spring Boot应用程序,我们将创建一个带有@SpringBootApplication 注释的类。
@SpringBootApplication
public class SpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
To test that everything is wired properly, let’s add code to create some test data.
为了测试所有的线路是否正确,让我们添加代码来创建一些测试数据。
We’ll define a method named initDb and annotate it with @PostConstruct so that the Spring container automatically calls this method as soon as the main class is initialized:
我们将定义一个名为initDb的方法,并用@PostConstruct对其进行注释,以便Spring容器在主类被初始化后自动调用该方法。
@PostConstruct
private void initDb() {
String sqlStatements[] = {
"drop table employees if exists",
"create table employees(id serial,first_name varchar(255),last_name varchar(255))",
"insert into employees(first_name, last_name) values('Eugen','Paraschiv')",
"insert into employees(first_name, last_name) values('Scott','Tiger')"
};
Arrays.asList(sqlStatements).forEach(sql -> {
jdbcTemplate.execute(sql);
});
// Query test data and print results
}
6. The Second Spring Boot Application
6.第二个Spring Boot应用程序
Now let’s look at the components of the client application, which requires the same Maven dependencies as defined above.
现在让我们看看客户端应用程序的组件,它需要的Maven依赖性与上面定义的一样。
First, we’ll override the data source properties. We need to ensure that the port number in the JDBC URL is the same as the one on which H2 is listening for incoming connections in the first application.
首先,我们将重写数据源属性。我们需要确保JDBC URL中的端口号与第一个应用程序中H2监听传入连接的端口号相同。
Here’s the application.properties file of the client application:
这里是客户端应用程序的application.properties文件。
spring.datasource.url=jdbc:h2:tcp://localhost:9090/mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create
Lastly, we create a main class of the client Spring Boot application.
最后,我们创建一个客户端Spring Boot应用程序的主类。
Again for simplicity, we define a @SpringBootApplication containing an initDb method with the @PostConstruct annotation:
为了简单起见,我们再次定义了一个@SpringBootApplication ,其中包含initDb方法,并带有@PostConstruct注解:。
@SpringBootApplication
public class ClientSpringBootApp {
public static void main(String[] args) {
SpringApplication.run(ClientSpringBootApp.class, args);
}
@PostConstruct
private void initDb() {
String sqlStatements[] = {
"insert into employees(first_name, last_name) values('Donald','Trump')",
"insert into employees(first_name, last_name) values('Barack','Obama')"
};
Arrays.asList(sqlStatements).forEach(sql -> {
jdbcTemplate.execute(sql);
});
// Fetch data using SELECT statement and print results
}
}
7. Sample Output
7.输出样本
Now, when we run both the applications one by one, we can check the console logs and confirm that the second application prints the data as expected.
现在,当我们一个接一个地运行这两个应用程序时,我们可以检查控制台日志,并确认第二个应用程序按照预期打印数据。
Here are the console logs of the first Spring Boot application:
下面是第一个Spring Boot应用程序的控制台日志:。
****** Creating table: Employees, and Inserting test data ******
drop table employees if exists
create table employees(id serial,first_name varchar(255),last_name varchar(255))
insert into employees(first_name, last_name) values('Eugen','Paraschiv')
insert into employees(first_name, last_name) values('Scott','Tiger')
****** Fetching from table: Employees ******
id:1,first_name:Eugen,last_name:Paraschiv
id:2,first_name:Scott,last_name:Tiger
And here are the console logs of the second Spring Boot application:
这里是第二个Spring Boot应用程序的控制台日志:。
****** Inserting more test data in the table: Employees ******
insert into employees(first_name, last_name) values('Donald','Trump')
insert into employees(first_name, last_name) values('Barack','Obama')
****** Fetching from table: Employees ******
id:1,first_name:Eugen,last_name:Paraschiv
id:2,first_name:Scott,last_name:Tiger
id:3,first_name:Donald,last_name:Trump
id:4,first_name:Barack,last_name:Obama
8. Conclusion
8.总结
In this quick article, we saw how we can access the same in-memory H2 database instance from multiple Spring Boot applications.
在这篇快速文章中,我们看到了如何从多个Spring Boot应用程序中访问同一个内存H2数据库实例。
As always, working code examples are available over on GitHub.
一如既往,在GitHub上可以找到工作代码的例子。