Как инициализировать компоненты после того, как JPA создает схемы? - PullRequest
0 голосов
/ 13 марта 2019

Context

Сервер работает с использованием Spring-Boot и использует данные Spring. База данных используется postgresql.

Задача

Некоторые компоненты читаются из information_schema, pg_user, pg_policies и pg_catalog. Эти компоненты PostConstruct являются в настоящий момент выполняется до создания схемы jpa. Это означает, что Информация о том, что компоненты пытаются получить, не была еще не создан jpa, поэтому компоненты аварийно завершают работу.

До исследования

Сама гибернация не выдает никаких ошибок. Запуск сервера дважды заставляет проблемные компоненты работать правильно. Из этого следует что эти компоненты работают до jpa.

Файл моих свойств содержит spring.jpa.hibernate.ddl-auto = update . я попытался найти код позади spring.jpa.hibernate.ddl-auto, чтобы увидеть, как Я мог бы заставить компоненты требовать этого с помощью @DependsOn, но я еще ничего не нашел на нем.

Я не могу просто ждать ApplicationReadyEvent с прослушивателем событий поскольку это нарушит зависимости между этими компонентами.

Код

Это мои источники данных хикари

@RequiredArgsConstructor
@Configuration
@EnableConfigurationProperties
public class DatabaseConfiguration {
    @Bean(name = "server")
    @ConfigurationProperties(prefix = "server.datasource")
    public HikariDataSource server() {
        return (HikariDataSource) DataSourceBuilder.create().build();
    }

    @Bean(name = "client")
    @ConfigurationProperties(prefix = "client.datasource")
    public HikariDataSource client() {
        return (HikariDataSource) DataSourceBuilder.create().build();
    }
}

У меня есть собственный компонент DataSource.

@Component
public class DatabaseRouterBean {
    private final AwsCognitoConfiguration cognitoConfiguration;
    private final DatabaseService databaseService;
    private final HikariDataSource server;
    private final HikariDataSource client;
    private final ModelSourceInformation modelSourceInformation;

    public DatabaseRouterBean(
        @Qualifier("server") final HikariDataSource server,
        @Qualifier("client") final HikariDataSource client,
        final AwsCognitoConfiguration cognitoConfiguration,
        final DatabaseService databaseService,
        final ModelSourceInformation modelSourceInformation
    ) {
        this.server = server;
        this.client = client;
        this.cognitoConfiguration = cognitoConfiguration;
        this.databaseService = databaseService;
        this.modelSourceInformation = modelSourceInformation;
    }

    @Bean
    @Primary
    public DatabaseRouter dataSource() {
        return new DatabaseRouter(cognitoConfiguration, databaseService, server, client, modelSourceInformation);
    }
}

Ниже приведена реализация источника данных.

// could have a better name
@RequiredArgsConstructor
@Log4j2
public class DatabaseRouter implements DataSource {
    private final AwsCognitoConfiguration config;
    private final DatabaseService databaseService;
    private final HikariDataSource superuser;
    private final HikariDataSource user;
    private final ModelSourceInformation modelSourceInformation;

Пользовательский компонент источника данных используется для создания соединений для менеджеров сущностей, использующих одну из двух учетных записей в базе данных для целей мультитенантности. Одна учетная запись является суперпользователем, а другая - ограниченной учетной записью. Многопользовательская аренда достигается за счет использования политик. Пользовательский источник данных выполняет SET_CONFIG для соединения.

DatabaseService - это класс обслуживания очень низкого уровня, который поддерживает чтение из information_schema, pg_user, pg_policies и pg_catalog.

@Service
@Log4j
public class DatabaseServiceImpl implements DatabaseService {
    private final HikariDataSource server;
    private final HikariDataSource client;

ModelSourceInformation не имеет зависимостей. Он используется для преобразования типа класса в имя переменной конфигурации и наоборот. Он используется пользовательским источником данных для заполнения SET_CONFIG в зависимости от типа пользователя. Он поддерживает определение переменных конфигурации и привязку их к моделям посредством аннотаций.

AwsCognitoConfiguration - это просто класс Configuration, который считывает настройки Cognito из файла свойств.

Определенный заказ на выполнение по зависимостям

  1. DatabaseConfiguration, ModelSourceInformation, AwsCognitoConfiguration
  2. DatabaseService
  3. DatabaseRouter
  4. JPA
  5. Остальные бобы

Следующие компоненты инициализируются до jpa. Их нужно инициализировать после jpa. Между ними есть зависимости.

  1. ModelDynamismInformation
  2. ModelEntityInformation
  3. ModelInformation
  4. ModelPrimaryKeyInformation
  5. ModelSchemaInformation
  6. ModelSecurityInformation
  7. PolicyInitializer

1 Ответ

1 голос
/ 14 марта 2019

Вы можете использовать @DependsOn для управления порядком инициализации бинов.Бин, зависящий от EntityManagerFactory, должен инициализироваться после того, как Hibernate выполнил создание своей схемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...