Перейти к основному содержимому

Доступ к одной и той же базе данных H2 в памяти в нескольких приложениях Spring Boot

· 4 мин. чтения

1. Обзор

В этом кратком руководстве мы покажем, как получить доступ к одной и той же базе данных H2 в памяти из нескольких приложений Spring Boot .

Для этого мы создадим два отдельных приложения Spring Boot. Первое приложение Spring Boot запустит экземпляр H2 в памяти, тогда как второе будет обращаться к встроенному экземпляру H2 первого приложения через TCP.

2. Фон

Как мы знаем, база данных в памяти работает быстрее и часто используется во встроенном режиме внутри приложения. Однако база данных в памяти не сохраняет данные при перезапуске сервера.

Для получения дополнительных сведений ознакомьтесь с нашими статьями о наиболее часто используемых базах данных в памяти и использовании базы данных в памяти в автоматизированном тестировании .

3. Зависимости Maven

Для двух приложений 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. Настройка источника данных H2

Во-первых, давайте определим самый важный компонент — компонент Spring для базы данных H2 в памяти — и предоставим его через TCP-порт:

@Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseaServer() throws SQLException {
return Server.createTcpServer(
"-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}

Методы, определенные параметрами initMethod и destroyMethod , вызываются Spring для запуска и остановки базы данных H2.

Параметр -tcp указывает H2 использовать TCP-сервер для запуска H2. Мы указываем TCP-порт, который будет использоваться, в третьем и четвертом параметрах метода createTcpServer .

Параметр tcpAllowOthers открывает H2 для доступа из внешних приложений, работающих на том же хосте или удаленных хостах.

Затем давайте переопределим источник данных по умолчанию, созданный функцией автоматической настройки Spring Boot, добавив несколько свойств в файл application.properties :

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

Важно переопределить эти свойства, потому что нам нужно будет использовать одни и те же свойства и значения в других приложениях , которые хотят совместно использовать одну и ту же базу данных H2.

5. Начальная загрузка первого приложения Spring Boot

Затем, чтобы загрузить наше приложение Spring Boot, мы создадим класс с аннотацией @SpringBootApplication :

@SpringBootApplication
public class SpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}

Чтобы проверить, что все подключено правильно, давайте добавим код для создания некоторых тестовых данных.

Мы определим метод с именем 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('ForEach','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. Второе загрузочное приложение Spring

Теперь давайте посмотрим на компоненты клиентского приложения, для которого требуются те же зависимости Maven, как определено выше.

Во-первых, мы переопределим свойства источника данных. Нам нужно убедиться, что номер порта в URL-адресе JDBC совпадает с номером порта, на котором H2 прослушивает входящие соединения в первом приложении.

Вот файл 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

Наконец, мы создаем основной класс клиентского приложения Spring Boot.

Снова для простоты мы определяем @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. Пример вывода

Теперь, когда мы запускаем оба приложения одно за другим, мы можем проверить журналы консоли и убедиться, что второе приложение печатает данные, как и ожидалось.

Вот журналы консоли первого приложения 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('ForEach','Paraschiv')
insert into employees(first_name, last_name) values('Scott','Tiger')
****** Fetching from table: Employees ******
id:1,first_name:ForEach,last_name:Paraschiv
id:2,first_name:Scott,last_name:Tiger

А вот логи консоли второго приложения 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:ForEach,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. Заключение

В этой быстрой статье мы увидели, как мы можем получить доступ к одному и тому же экземпляру базы данных H2 в памяти из нескольких приложений Spring Boot .

Как всегда, примеры рабочего кода доступны на GitHub .